home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / games / wormwars / source / engine2.c < prev    next >
C/C++ Source or Header  |  2004-08-03  |  106KB  |  2,826 lines

  1. // 1. INCLUDES -----------------------------------------------------------
  2.  
  3. #include "stdafx.h"
  4. #include "diff.h"
  5. #include "same.h"
  6. #include "engine.h"
  7.  
  8. #include <stdlib.h>                    // abs()
  9.  
  10. // 2. DEFINES ------------------------------------------------------------
  11.  
  12. // 3. EXPORTED VARIABLES -------------------------------------------------
  13.  
  14. AGLOBAL UBYTE birdframes[BIRDFRAMES + 1] =
  15. { BIRD,
  16.   FIRSTBIRDFRAME,
  17.   FIRSTBIRDFRAME + 1,
  18.   FIRSTBIRDFRAME + 2,
  19.   FIRSTBIRDFRAME + 3
  20. },
  21. missileframes[4][MISSILEFRAMES + 1] =
  22. { { FIRSTMISSILE,          // green (p1)
  23.     FIRSTMISSILEFRAME,
  24.     FIRSTMISSILEFRAME + 1,
  25.     FIRSTMISSILEFRAME + 2,
  26.     FIRSTMISSILEFRAME + 3,
  27.     FIRSTMISSILEFRAME + 4
  28.   },                       
  29.   { FIRSTMISSILE + 1,      // red (p2)
  30.     FIRSTMISSILEFRAME + 5,            
  31.     FIRSTMISSILEFRAME + 6,
  32.     FIRSTMISSILEFRAME + 7,
  33.     FIRSTMISSILEFRAME + 8,
  34.     FIRSTMISSILEFRAME + 9
  35.   },
  36.   { FIRSTMISSILE + 2,      // blue (p3)
  37.     FIRSTMISSILEFRAME + 10,
  38.     FIRSTMISSILEFRAME + 11,
  39.     FIRSTMISSILEFRAME + 12,
  40.     FIRSTMISSILEFRAME + 13,
  41.     FIRSTMISSILEFRAME + 14,
  42.   },
  43.   { FIRSTMISSILE + 3,      // yellow (p4)
  44.     FIRSTMISSILEFRAME + 15,
  45.     FIRSTMISSILEFRAME + 16,
  46.     FIRSTMISSILEFRAME + 17,
  47.     FIRSTMISSILEFRAME + 18,
  48.     FIRSTMISSILEFRAME + 19
  49. } },
  50. bananaframes[4][BANANAFRAMES + 1] =
  51. { { FIRSTBANANA,
  52.     FIRSTBANANAFRAME +  0,
  53.     FIRSTBANANAFRAME +  1,
  54.     FIRSTBANANAFRAME +  2,
  55.     FIRSTBANANAFRAME +  3,
  56.     FIRSTBANANAFRAME +  4,
  57.     FIRSTBANANAFRAME +  5,
  58.     FIRSTBANANAFRAME +  6,
  59.   },
  60.   { FIRSTBANANA + 1,
  61.     FIRSTBANANAFRAME +  7,
  62.     FIRSTBANANAFRAME +  8,
  63.     FIRSTBANANAFRAME +  9,
  64.     FIRSTBANANAFRAME + 10,
  65.     FIRSTBANANAFRAME + 11,
  66.     FIRSTBANANAFRAME + 12,
  67.     FIRSTBANANAFRAME + 13,
  68.   },
  69.   { FIRSTBANANA + 2,
  70.     FIRSTBANANAFRAME + 14,
  71.     FIRSTBANANAFRAME + 15,
  72.     FIRSTBANANAFRAME + 16,
  73.     FIRSTBANANAFRAME + 17,
  74.     FIRSTBANANAFRAME + 18,
  75.     FIRSTBANANAFRAME + 19,
  76.     FIRSTBANANAFRAME + 20,
  77.   },
  78.   { FIRSTBANANA + 3,
  79.     FIRSTBANANAFRAME + 21,
  80.     FIRSTBANANAFRAME + 22,
  81.     FIRSTBANANAFRAME + 23,
  82.     FIRSTBANANAFRAME + 24,
  83.     FIRSTBANANAFRAME + 25,
  84.     FIRSTBANANAFRAME + 26,
  85.     FIRSTBANANAFRAME + 27,
  86. } };
  87.  
  88. // 4. IMPORTED VARIABLES -------------------------------------------------
  89.  
  90. // from engine1.c
  91. IMPORT ABOOL                     banging,
  92.                                  enclosed;
  93. IMPORT UBYTE                     field[MAXFIELDX + 1][MAXFIELDY + 1],
  94.                                  tailfield[MAXFIELDX + 1][MAXFIELDY + 1];
  95. IMPORT SBYTE                     level,
  96.                                  numberx,
  97.                                  numbery,
  98.                                  number,
  99.                                  treasurer,
  100.                                  players,
  101.                                  levels,
  102.                                  reallevel;
  103. IMPORT SWORD                     fieldx, fieldy,
  104.                                  secondsleft,
  105.                                  secondsperlevel;
  106. IMPORT ULONG                     r;
  107. IMPORT struct CreatureStruct     creature[CREATURES + 1];
  108. IMPORT struct MagnetStruct       magnet[MAGNETS + 1];
  109. IMPORT struct ObjectStruct       object[LASTOBJECT + 1];
  110. IMPORT struct ProtectorStruct    protector[4][PROTECTORS + 1];
  111. IMPORT struct TeleportStruct     teleport[2];
  112. IMPORT struct WormStruct         worm[4];
  113. IMPORT struct CreatureInfoStruct creatureinfo[SPECIES + 1];
  114.  
  115. // 5. MODULE VARIABLES ---------------------------------------------------
  116.  
  117. // 6. MODULE STRUCTURES --------------------------------------------------
  118.  
  119. MODULE struct
  120. {   SBYTE deltax, deltay;
  121. } thedogqueue[CREATURES + 1][DOGQUEUELIMIT + 1];
  122. MODULE struct
  123. {   SBYTE deltax, deltay;
  124. } thewormqueue[4][WORMQUEUELIMIT + 1];
  125. struct
  126. {   SBYTE x, y, deltax, deltay;
  127.     ABOOL alive, moved, teleported, visible, reflected;
  128. } bullet[9];
  129. MODULE UBYTE eachtail[4][2][9][9] = {
  130. { { { GN_SE_NW,      GN_SE_N,       GN_SE_NE, // going NW (delta -1, -1)
  131.       GN_SE_W,       WHATEVER,      GN_SE_E,  // (so starting from SE)
  132.       GN_SE_SW,      GN_SE_S,       GN_SE_NW
  133.     },
  134.     { GN_S_NW,       GN_S_N,        GN_S_NE,  // going N (delta 0, -1)
  135.       GN_S_W,        WHATEVER,      GN_S_E,   // (so starting from S)
  136.       GN_S_SW,       GN_S_N,        GN_S_SE
  137.     },
  138.     { GN_SW_NW,      GN_SW_N,       GN_SW_NE, // going NE (delta 0, 1)
  139.       GN_SW_W,       WHATEVER,      GN_SW_E,  // (so starting from SW)
  140.       GN_SW_NE,      GN_SW_S,       GN_SW_SE
  141.     },
  142.     { GN_E_NW,       GN_E_N,        GN_E_NE,  // going W (delta -1, 0)
  143.       GN_E_W,        WHATEVER,      GN_E_W,   // (so starting from E)
  144.       GN_E_SW,       GN_E_S,        GN_E_SE
  145.     },
  146.     { GN_SE_NW,      GN_S_N,        GN_SW_NE, // going nowhere (delta 0, 0)
  147.       GN_E_W,        WHATEVER,      GN_W_E,  
  148.       GN_NE_SW,      GN_N_S,        GN_NW_SE
  149.     },
  150.     { GN_W_NW,       GN_W_N,        GN_W_NE,  // going E (delta 1, 0)
  151.       GN_W_E,        WHATEVER,      GN_W_E,   // (so starting from W)
  152.       GN_W_SW,       GN_W_S,        GN_W_SE
  153.     },
  154.     { GN_NE_NW,      GN_NE_N,       GN_NE_NW, // going SW (delta -1, 1)
  155.       GN_NE_W,       WHATEVER,      GN_NE_E,  // (so starting from NE)
  156.       GN_NE_SW,      GN_NE_S,       GN_NE_SE
  157.     },
  158.     { GN_N_NW,       GN_N_S,        GN_N_NE,  // going S (delta 0, 1)
  159.       GN_N_W,        WHATEVER,      GN_N_E,   // (so starting from N)
  160.       GN_N_SW,       GN_N_S,        GN_N_SE
  161.     },
  162.     { GN_NW_SE,      GN_NW_N,       GN_NW_NE, // going SE (delta 1, 1)
  163.       GN_NW_W,       WHATEVER,      GN_NW_E,  // (so starting from NW)
  164.       GN_NW_SW,      GN_NW_S,       GN_NW_SE
  165.   } },
  166.   { { GG_SE_NW,      GG_SE_N,       GG_SE_NE, // going NW (delta -1, -1)
  167.       GG_SE_W,       WHATEVER,      GG_SE_E,  // (so starting from SE)
  168.       GG_SE_SW,      GG_SE_S,       GG_SE_NW
  169.     },
  170.     { GG_S_NW,       GG_S_N,        GG_S_NE,  // going N (delta 0, -1)
  171.       GG_S_W,        WHATEVER,      GG_S_E,   // (so starting from S)
  172.       GG_S_SW,       GG_S_N,        GG_S_SE
  173.     },
  174.     { GG_SW_NW,      GG_SW_N,       GG_SW_NE, // going NE (delta 0, 1)
  175.       GG_SW_W,       WHATEVER,      GG_SW_E,  // (so starting from SW)
  176.       GG_SW_NE,      GG_SW_S,       GG_SW_SE
  177.     },                
  178.     { GG_E_NW,       GG_E_N,        GG_E_NE,  // going W (delta -1, 0)
  179.       GG_E_W,        WHATEVER,      GG_E_W,   // (so starting from E)
  180.       GG_E_SW,       GG_E_S,        GG_E_SE
  181.     },
  182.     { GG_SE_NW,      GG_S_N,        GG_SW_NE, // going nowhere (delta 0, 0)
  183.       GG_E_W,        WHATEVER,      GG_W_E,  
  184.       GG_NE_SW,      GG_N_S,        GG_NW_SE
  185.     },
  186.     { GG_W_NW,       GG_W_N,        GG_W_NE,  // going E (delta 1, 0)
  187.       GG_W_E,        WHATEVER,      GG_W_E,   // (so starting from W)
  188.       GG_W_SW,       GG_W_S,        GG_W_SE
  189.     },
  190.     { GG_NE_NW,      GG_NE_N,       GG_NE_SW, // going SW (delta -1, 1)
  191.       GG_NE_W,       WHATEVER,      GG_NE_E,  // (so starting from NE)
  192.       GG_NE_SW,      GG_NE_S,       GG_NE_SE
  193.     },
  194.     { GG_N_NW,       GG_N_S,        GG_N_NE,  // going S (delta 0, 1)
  195.       GG_N_W,        WHATEVER,      GG_N_E,   // (so starting from N)
  196.       GG_N_SW,       GG_N_S,        GG_N_SE
  197.     },
  198.     { GG_NW_SE,      GG_NW_N,       GG_NW_NE, // going SE (delta 1, 1)
  199.       GG_NW_W,       WHATEVER,      GG_NW_E,  // (so starting from NW)
  200.       GG_NW_SW,      GG_NW_S,       GG_NW_SE
  201. } } },
  202. { { { RN_SE_NW,      RN_SE_N,       RN_SE_NE, // going NW (delta -1, -1)
  203.       RN_SE_W,       WHATEVER,      RN_SE_E,  // (so starting from SE)
  204.       RN_SE_SW,      RN_SE_S,       RN_SE_NW,
  205.     },                              
  206.     { RN_S_NW,       RN_S_N,        RN_S_NE,  // going N (delta 0, -1)
  207.       RN_S_W,        WHATEVER,      RN_S_E,   // (so starting from S)
  208.       RN_S_SW,       RN_S_N,        RN_S_SE
  209.     },
  210.     { RN_SW_NW,      RN_SW_N,       RN_SW_NE, // going NE (delta 0, 1)
  211.       RN_SW_W,       WHATEVER,      RN_SW_E,  // (so starting from SW)
  212.       RN_SW_NE,      RN_SW_S,       RN_SW_SE
  213.     },
  214.     { RN_E_NW,       RN_E_N,        RN_E_NE,  // going W (delta -1, 0)
  215.       RN_E_W,        WHATEVER,      RN_E_W,   // (so starting from E)
  216.       RN_E_SW,       RN_E_S,        RN_E_SE
  217.     },
  218.     { RN_SE_NW,      RN_S_N,        RN_SW_NE, // going nowhere (delta 0, 0)
  219.       RN_E_W,        WHATEVER,      RN_W_E,  
  220.       RN_NE_SW,      RN_N_S,        RN_NW_SE
  221.     },
  222.     { RN_W_NW,       RN_W_N,        RN_W_NE,  // going E (delta 1, 0)
  223.       RN_W_E,        WHATEVER,      RN_W_E,   // (so starting from W)
  224.       RN_W_SW,       RN_W_S,        RN_W_SE
  225.     },
  226.     { RN_NE_NW,      RN_NE_N,       RN_NE_SW, // going SW (delta -1, 1)
  227.       RN_NE_W,       WHATEVER,      RN_NE_E,  // (so starting from NE)
  228.       RN_NE_SW,      RN_NE_S,       RN_NE_SE
  229.     },
  230.     { RN_N_NW,       RN_N_S,        RN_N_NE,  // going S (delta 0, 1)
  231.       RN_N_W,        WHATEVER,      RN_N_E,   // (so starting from N)
  232.       RN_N_SW,       RN_N_S,        RN_N_SE
  233.     },
  234.     { RN_NW_SE,      RN_NW_N,       RN_NW_NE, // going SE (delta 1, 1)
  235.       RN_NW_W,       WHATEVER,      RN_NW_E,  // (so starting from NW)
  236.       RN_NW_SW,      RN_NW_S,       RN_NW_SE
  237.   } },
  238.   { { RG_SE_NW,      RG_SE_N,       RG_SE_NE, // going NW (delta -1, -1)
  239.       RG_SE_W,       WHATEVER,      RG_SE_E,  // (so starting from SE)
  240.       RG_SE_SW,      RG_SE_S,       RG_SE_NW
  241.     },
  242.     { RG_S_NW,       RG_S_N,        RG_S_NE,  // going N (delta 0, -1)
  243.       RG_S_W,        WHATEVER,      RG_S_E,   // (so starting from S)
  244.       RG_S_SW,       RG_S_N,        RG_S_SE
  245.     },
  246.     { RG_SW_NW,      RG_SW_N,       RG_SW_NE, // going NE (delta 0, 1)
  247.       RG_SW_W,       WHATEVER,      RG_SW_E,  // (so starting from SW)
  248.       RG_SW_NE,      RG_SW_S,       RG_SW_SE
  249.     },
  250.     { RG_E_NW,       RG_E_N,        RG_E_NE,  // going W (delta -1, 0)
  251.       RG_E_W,        WHATEVER,      RG_E_W,   // (so starting from E)
  252.       RG_E_SW,       RG_E_S,        RG_E_SE
  253.     },
  254.     { RG_SE_NW,      RG_S_N,        RG_SW_NE, // going nowhere (delta 0, 0)
  255.       RG_E_W,        WHATEVER,      RG_W_E,  
  256.       RG_NE_SW,      RG_N_S,        RG_NW_SE
  257.     },
  258.     { RG_W_NW,       RG_W_N,        RG_W_NE,  // going E (delta 1, 0)
  259.       RG_W_E,        WHATEVER,      RG_W_E,   // (so starting from W)
  260.       RG_W_SW,       RG_W_S,        RG_W_SE
  261.     },
  262.     { RG_NE_NW,      RG_NE_N,       RG_NE_SW, // going SW (delta -1, 1)
  263.       RG_NE_W,       WHATEVER,      RG_NE_E,  // (so starting from NE)
  264.       RG_NE_SW,      RG_NE_S,       RG_NE_SE
  265.     },
  266.     { RG_N_NW,       RG_N_S,        RG_N_NE,  // going S (delta 0, 1)
  267.       RG_N_W,        WHATEVER,      RG_N_E,   // (so starting from N)
  268.       RG_N_SW,       RG_N_S,        RG_N_SE
  269.     },
  270.     { RG_NW_SE,      RG_NW_N,       RG_NW_NE, // going SE (delta 1, 1)
  271.       RG_NW_W,       WHATEVER,      RG_NW_E,  // (so starting from NW)
  272.       RG_NW_SW,      RG_NW_S,       RG_NW_SE
  273. } } },
  274. { { { BN_NW_SE,      BN_N_SE,       BN_NE_SE, // going NW (delta -1, -1)
  275.       BN_W_SE,       WHATEVER,      BN_E_SE,  // (so starting from SE)
  276.       BN_SW_SE,      BN_S_SE,       BN_NW_SE
  277.     },                              
  278.     { BN_NW_S,       BN_N_S,        BN_NE_S,  // going N (delta 0, -1)
  279.       BN_W_S,        WHATEVER,      BN_E_S,   // (so starting from S)
  280.       BN_S_SW,       BN_N_S,        BN_S_SE
  281.     },
  282.     { BN_NW_SW,      BN_N_SW,       BN_NE_SW, // going NE (delta 0, 1)
  283.       BN_W_SW,       WHATEVER,      BN_SW_E,  // (so starting from SW)
  284.       BN_NE_SW,      BN_S_SW,       BN_SW_SE
  285.     },
  286.     { BN_NW_E,       BN_N_E,        BN_E_NE,  // going W (delta -1, 0)
  287.       BN_W_E,        WHATEVER,      BN_W_E,   // (so starting from E)
  288.       BN_SW_E,       BN_E_S,        BN_E_SE
  289.     },
  290.     { BN_NW_SE,      BN_N_S,        BN_NE_SW, // going nowhere (delta 0, 0)
  291.       BN_W_E,        WHATEVER,      BN_W_E,  
  292.       BN_NE_SW,      BN_N_S,        BN_NW_SE
  293.     },
  294.     { BN_W_NW,       BN_N_W,        BN_W_NE,  // going E (delta 1, 0)
  295.       BN_W_E,        WHATEVER,      BN_W_E,   // (so starting from W)
  296.       BN_W_SW,       BN_W_S,        BN_W_SE
  297.     },
  298.     { BN_NW_NE,      BN_N_NE,       BN_NE_SW, // going SW (delta -1, 1)
  299.       BN_W_NE,       WHATEVER,      BN_E_NE,  // (so starting from NE)
  300.       BN_NE_SW,      BN_NE_S,       BN_NE_SE
  301.     },
  302.     { BN_N_NW,       BN_N_S,        BN_N_NE,  // going S (delta 0, 1)
  303.       BN_N_W,        WHATEVER,      BN_N_E,   // (so starting from N)
  304.       BN_N_SW,       BN_N_S,        BN_N_SE
  305.     },
  306.     { BN_SW_SE,      BN_N_NW,       BN_NW_NE, // going SE (delta 1, 1)
  307.       BN_W_NW,       WHATEVER,      BN_NW_E,  // (so starting from NW)
  308.       BN_NW_SW,      BN_NW_S,       BN_NW_SE
  309.   } },
  310.   { { BG_NW_SE,      BG_N_SE,       BG_NE_SE, // going NW (delta -1, -1)
  311.       BG_W_SE,       WHATEVER,      BG_E_SE,  // (so starting from SE)
  312.       BG_SW_SE,      BG_S_SE,       BG_NW_SE
  313.     },
  314.     { BG_NW_S,       BG_N_S,        BG_NE_S,  // going N (delta 0, -1)
  315.       BG_W_S,        WHATEVER,      BG_E_S,   // (so starting from S)
  316.       BG_S_SW,       BG_N_S,        BG_S_SE
  317.     },
  318.     { BG_NW_SW,      BG_N_SW,       BG_NE_SW, // going NE (delta 0, 1)
  319.       BG_W_SW,       WHATEVER,      BG_SW_E,  // (so starting from SW)
  320.       BG_NE_SW,      BG_S_SW,       BG_SW_SE
  321.     },
  322.     { BG_NE_E,       BG_N_E,        BG_NE_E,  // going W (delta -1, 0)
  323.       BG_W_E,        WHATEVER,      BG_W_E,   // (so starting from E)
  324.       BG_SW_E,       BG_E_S,        BG_E_SE
  325.     },
  326.     { BG_NW_SE,      BG_N_S,        BG_NE_SW, // going nowhere (delta 0, 0)
  327.       BG_W_E,        WHATEVER,      BG_W_E,  
  328.       BG_NE_SW,      BG_N_S,        BG_NW_SE
  329.     },
  330.     { BG_NW_W,       BG_N_W,        BG_NE_W,  // going E (delta 1, 0)
  331.       BG_W_E,        WHATEVER,      BG_W_E,   // (so starting from W)
  332.       BG_W_SW,       BG_W_S,        BG_W_SE
  333.     },
  334.     { BG_NW_NE,      BG_N_NE,       BG_NE_SW, // going SW (delta -1, 1)
  335.       BG_NE_W,       WHATEVER,      BG_NE_E,  // (so starting from NE)
  336.       BG_NE_SW,      BG_NE_S,       BG_NE_SE
  337.     },
  338.     { BG_N_NW,       BG_N_S,        BG_N_NE,  // going S (delta 0, 1)
  339.       BG_N_W,        WHATEVER,      BG_N_E,   // (so starting from N)
  340.       BG_N_SW,       BG_N_S,        BG_N_SE
  341.     },
  342.     { BG_NW_SE,      BG_N_NW,       BG_NW_NE, // going SE (delta 1, 1)
  343.       BG_NW_W,       WHATEVER,      BG_NW_E,  // (so starting from NW)
  344.       BG_NW_SW,      BG_NW_S,       BG_NW_SE
  345. } } },
  346. { { { YN_NW_SE,      YN_N_SE,       YN_NE_SE, // going NW (delta -1, -1)
  347.       YN_W_SE,       WHATEVER,      YN_E_SE,  // (so starting from SE)
  348.       YN_SW_SE,      YN_S_SE,       YN_NW_SE
  349.     },                              
  350.     { YN_NW_S,       YN_N_S,        YN_NE_S,  // going N (delta 0, -1)
  351.       YN_W_S,        WHATEVER,      YN_S_E,   // (so starting from S)
  352.       YN_S_SW,       YN_N_S,        YN_S_SE
  353.     },
  354.     { YN_NW_SW,      YN_N_SW,       YN_NE_SW, // going NE (delta 0, 1)
  355.       YN_W_SW,       WHATEVER,      YN_E_SW,  // (so starting from SW)
  356.       YN_NE_SW,      YN_S_SW,       YN_SW_SE
  357.     },
  358.     { YN_NW_E,       YN_N_E,        YN_NE_E,  // going W (delta -1, 0)
  359.       YN_W_E,        WHATEVER,      YN_W_E,   // (so starting from E)
  360.       YN_E_SW,       YN_S_E,        YN_E_SE
  361.     },
  362.     { YN_NW_SE,      YN_N_S,        YN_NE_SW, // going nowhere (delta 0, 0)
  363.       YN_W_E,        WHATEVER,      YN_W_E,  
  364.       YN_NE_SW,      YN_N_S,        YN_NW_SE
  365.     },
  366.     { YN_NW_W,       YN_N_W,        YN_W_NE,  // going E (delta 1, 0)
  367.       YN_W_E,        WHATEVER,      YN_W_E,   // (so starting from W)
  368.       YN_W_SW,       YN_W_S,        YN_W_SE
  369.     },
  370.     { YN_NW_NE,      YN_N_NE,       YN_NE_SW, // going SW (delta -1, 1)
  371.       YN_W_NE,       WHATEVER,      YN_NE_E,  // (so starting from NE)
  372.       YN_NE_SW,      YN_NE_S,       YN_NE_SE
  373.     },
  374.     { YN_N_NW,       YN_N_S,        YN_N_NE,  // going S (delta 0, 1)
  375.       YN_N_W,        WHATEVER,      YN_N_E,   // (so starting from N)
  376.       YN_N_SW,       YN_N_S,        YN_N_SE
  377.     },
  378.     { YN_NW_SE,      YN_N_NW,       YN_NW_NE, // going SE (delta 1, 1)
  379.       YN_NW_W,       WHATEVER,      YN_NW_E,  // (so starting from NW)
  380.       YN_NW_SW,      YN_NW_S,       YN_NW_SE
  381.   } },
  382.   { { YG_NW_SE,      YG_N_SE,       YG_NE_SE, // going NW (delta -1, -1)
  383.       YG_W_SE,       WHATEVER,      YG_E_SE,  // (so starting from SE)
  384.       YG_SW_SE,      YG_S_SE,       YG_NW_SE
  385.     },                              
  386.     { YG_S_NW,       YG_N_S,        YG_S_NE,  // going N (delta 0, -1)
  387.       YG_W_S,        WHATEVER,      YG_E_S,   // (so starting from S)
  388.       YG_S_SW,       YG_N_S,        YG_S_SE
  389.     },
  390.     { YG_NW_SW,      YG_N_SW,       YG_NE_SW, // going NE (delta 0, 1)
  391.       YG_W_SW,       WHATEVER,      YG_E_SW,  // (so starting from SW)
  392.       YG_NE_SW,      YG_S_SW,       YG_SW_SE
  393.     },
  394.     { YG_E_NW,       YG_E_N,        YG_E_NE,  // going W (delta -1, 0)
  395.       YG_W_E,        WHATEVER,      YG_W_E,   // (so starting from E)
  396.       YG_E_SW,       YG_E_S,        YG_E_SE
  397.     },
  398.     { YG_NW_SE,      YG_N_S,        YG_NE_SW, // going nowhere (delta 0, 0)
  399.       YG_W_E,        WHATEVER,      YG_W_E,  
  400.       YG_NE_SW,      YG_N_S,        YG_NW_SE
  401.     },
  402.     { YG_W_NW,       YG_N_W,        YG_W_NE,  // going E (delta 1, 0)
  403.       YG_W_E,        WHATEVER,      YG_W_E,   // (so starting from W)
  404.       YG_W_SW,       YG_W_S,        YG_W_SE
  405.     },
  406.     { YG_NW_NE,      YG_N_NE,       YG_NE_SW, // going SW (delta -1, 1)
  407.       YG_W_NE,       WHATEVER,      YG_E_NE,  // (so starting from NE)
  408.       YG_NE_SW,      YG_S_NE,       YG_NE_SE
  409.     },
  410.     { YG_N_NW,       YG_N_S,        YG_N_NE,  // going S (delta 0, 1)
  411.       YG_N_W,        WHATEVER,      YG_E_N,   // (so starting from N)
  412.       YG_N_SW,       YG_N_S,        YG_N_SE
  413.     },
  414.     { YG_NW_SE,      YG_N_NW,       YG_NW_NE, // going SE (delta 1, 1)
  415.       YG_W_NW,       WHATEVER,      YG_E_NW,  // (so starting from NW)
  416.       YG_NW_SW,      YG_S_NW,       YG_NW_SE
  417. } } }
  418. };
  419.  
  420. // 7. MODULE FUNCTIONS ---------------------------------------------------
  421.  
  422. MODULE void creaturebullet(SBYTE x, SBYTE y, SBYTE deltax, SBYTE deltay, UBYTE subspecies);
  423. MODULE void creaturecreature(UBYTE which1, UBYTE which2);
  424. MODULE ABOOL bouncecreature(UBYTE which, SBYTE x, SBYTE y);
  425. MODULE void bounceoffcreature(UBYTE which, SBYTE x, SBYTE y);
  426. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay);
  427. MODULE void protcol(SBYTE player, SBYTE x, SBYTE y, SBYTE thisprot);
  428. MODULE void wormbullet(SBYTE player);
  429. MODULE void choosediagonal(UBYTE which);
  430. MODULE void chooseorthagonal(SBYTE* xx, SBYTE* yy);
  431. MODULE void protectorloop1(SBYTE player);
  432. MODULE void protectorloop2(SBYTE player);
  433. MODULE void turncreature(UBYTE which);
  434.  
  435. // 8. CODE ---------------------------------------------------------------
  436.  
  437. AGLOBAL void createcreature(UBYTE species,
  438.                             UBYTE which,
  439.                             SBYTE x,
  440.                             SBYTE y,
  441.                             SBYTE deltax,
  442.                             SBYTE deltay,
  443.                             UBYTE player,
  444.                             UBYTE subspecies
  445.                            )
  446. {   if (species != ORB)
  447.     {   creature[which].deltax  = deltax;
  448.         creature[which].deltay  = deltay;
  449.     }
  450.  
  451.     if (species != CAMEL)
  452.     {   creature[which].subspecies = subspecies;
  453.     }
  454.  
  455.     if (species == MISSILE_C)
  456.     {    creature[which].visible = FALSE;
  457.     } else creature[which].visible = TRUE;
  458.  
  459. /*  This is something of a workaround to get around the problem where the
  460.     tail/glow that eg. a fish appears on is not restored to the correct
  461.     glow-image...
  462.     if (creatureinfo[species - FIRSTCREATURE].wall == TRUE)
  463.     {   creature[which].last = creature[which].oldlast = field[x][y];
  464.     } else */
  465.     creature[which].last = creature[which].oldlast = EMPTY;
  466.  
  467.     creature[which].alive   = TRUE;
  468.     creature[which].x       = x;
  469.     creature[which].y       = y;
  470.     creature[which].species = species;
  471.     creature[which].player  = player;
  472.     creature[which].speed   = creatureinfo[species - FIRSTCREATURE].speed;
  473.     creature[which].score   = creatureinfo[species - FIRSTCREATURE].score;
  474.  
  475.     switch(species)
  476.     {
  477.     case HORSE:
  478.         creature[which].dir      = arand(7);
  479.         turncreature(which);
  480.     break;
  481.     case MONKEY:
  482.         creature[which].dir      =
  483.         creature[which].pos      = 0;
  484.     break;
  485.     case OCTOPUS:
  486.         creature[which].dir      =
  487.         creature[which].pos      = -1;
  488.     break;
  489.     case DOG:
  490.         creature[which].pos      = -1;
  491.         creature[which].dormant  = DORMANT; /* dormant */
  492.     break;
  493.     case ORB:
  494.         creature[which].deltax   = (arand(1) * 2) - 1;
  495.         creature[which].deltay   = (arand(1) * 2) - 1;
  496.     break;
  497.     case RAIN:
  498.         effect(FXBORN_RAIN);
  499.     break;
  500.     case CYCLONE_C:
  501.         effect(FXGET_CYCLONE);
  502.     break;
  503.     case MISSILE_C:
  504.         effect(FXBORN_MISSILE);
  505.         creature[which].frame    = 0;
  506.     break;
  507.     case BIRD:
  508.         creature[which].frame    = 0;
  509.         creature[which].dir      = 1;
  510.     break;
  511.     case SPIDER:
  512.         creature[which].last     = FROST;
  513.     break;
  514.     case OTTER:
  515.         if (x == 0)
  516.         {   creature[which].going    = OTTER_DOWN;
  517.             creature[which].journey  = OTTER_RIGHT;
  518.         } else
  519.         {   creature[which].going    = OTTER_UP;
  520.             creature[which].journey  = OTTER_LEFT;
  521.         }
  522.         creature[which].last       =
  523.         creature[which].oldlast    = STONE;
  524.     break;
  525.     case CAMEL:
  526.         creature[which].subspecies = arand(LASTOBJECT);
  527.     break;
  528.     case FRAGMENT:
  529.         if (creature[which].subspecies == BANANA)
  530.         {   creature[which].player = arand(3);
  531.             creature[which].score  = POINTS_BANANA;
  532.             creature[which].frame  = 0;
  533.             if (!arand(1))
  534.             {   creature[which].dir = 1;
  535.             } else
  536.             {   creature[which].dir = -1;
  537.         }   }
  538.     break;
  539.     case BULL:
  540.         if (!arand(1))
  541.         {   creature[which].dir    = 1;
  542.             draw(x, y, BULLRIGHT);
  543.         } else
  544.         {   creature[which].dir    = -1;
  545.             draw(x, y, BULLLEFT);
  546.         }
  547.         field[x][y] = BULL;
  548.     break;
  549.     case RABBIT:
  550.         if (deltax == 1)
  551.         {   draw(x, y, RABBITRIGHT);
  552.         } else
  553.         {   // assert(deltax == -1);
  554.             draw(x, y, RABBITLEFT);
  555.         }
  556.         // no need to worry about .dir, it is not used for rabbits
  557.         field[x][y] = RABBIT;
  558.     break;
  559.     case FROG:
  560.         if (!arand(2))
  561.         {   creature[which].dir    = 1;
  562.             draw(x, y, FROGRIGHT);
  563.         } else
  564.         {   creature[which].dir    = -1;
  565.             draw(x, y, FROGLEFT);
  566.         }
  567.         field[x][y] = FROG;
  568.     break;
  569.     default:
  570.     break;
  571.     }
  572.  
  573.     if (creature[which].visible)
  574.     {   drawcreature(which);
  575.     }
  576.  
  577.     if (level > 5 && creature[which].speed >= 2)
  578.         creature[which].speed--;
  579.     if (level > 10 && creature[which].speed >= 2)
  580.         creature[which].speed--;
  581.     if (level > 15 && creature[which].speed >= 2)
  582.         creature[which].speed--;
  583.     if (level > 20 && creature[which].speed >= 2)
  584.         creature[which].speed--;
  585. }
  586.  
  587. AGLOBAL void creatureloop(SBYTE which)
  588. {   UBYTE bestdistance, c, i, distance, player;
  589.     SBYTE x, xx, xxx, xmin, xmax, frontx, rearx,
  590.           y, yy, yyy, ymin, ymax, fronty, reary;
  591.     FLAG  done;
  592.  
  593.     x = creature[which].x;
  594.     y = creature[which].y;
  595.  
  596.     if (!valid(x, y)) // defensive programming
  597.     {   creature[which].alive = FALSE;
  598.         return;
  599.  
  600.         /* TEXT temp1[SAYLIMIT + 1], temp2[8];
  601.  
  602.         strcpy(temp1, "BAD CREATURE AT x: ");
  603.         stci_d(temp2, x);
  604.         strcat(temp1, temp2);
  605.         strcat(temp1, ", y: ");
  606.         stci_d(temp2, y);
  607.         strcat(temp1, temp2);
  608.         strcat(temp1, "!");
  609.         say(temp1, PURPLE);
  610.         draw(fieldx + 1, 0, creature[which].species); // indicates which creature
  611.         Delay(250);
  612.         clearkybd();
  613.         anykey(FALSE); */
  614.     }
  615.  
  616.     /* decide whether and where to move */
  617.  
  618.     switch(creature[which].species)
  619.     {
  620.     case BIRD:
  621.         if (creature[which].player == 255)
  622.         {   bestdistance = 255;
  623.             for (player = 0; player <= 3; player++)
  624.             {   if (worm[player].lives)
  625.                 {   xx = abs(worm[player].x - x);
  626.                     yy = abs(worm[player].y - y);
  627.                     if (xx > yy)
  628.                         distance = xx;
  629.                     else distance = yy;
  630.                     if (distance <= DISTANCE_BIRD && distance < bestdistance)
  631.                     {   effect(FXBORN_BIRD);
  632.                         bestdistance = distance;
  633.                         creature[which].player = player;
  634.         }   }   }   }
  635.         if (creature[which].player != 255) // if swooping
  636.         {   if (worm[creature[which].player].lives)
  637.             {   creature[which].deltax = bsign(worm[creature[which].player].x - x);
  638.                 creature[which].deltay = bsign(worm[creature[which].player].y - y);
  639.             } else
  640.             {   creature[which].player = 255; // return to dormancy
  641.                 creature[which].deltax = creature[which].deltay = 0;
  642.         }   }
  643.     break;
  644.     case CAMEL:
  645.         xx = x + creature[which].deltax;
  646.         yy = y + creature[which].deltay;
  647.         if
  648.         (   !arand(FREQ_CAMELTURN)
  649.          || ((!creature[which].deltax) && (!creature[which].deltay))
  650.          || !valid(xx, yy)
  651.          || field[xx][yy] < FIRSTEMPTY
  652.          || field[xx][yy] > LASTEMPTY
  653.         )
  654.         {   do
  655.             {   xx = arand(2) - 1;
  656.                 yy = arand(2) - 1;
  657.             } while (!valid(x + xx, y + yy));
  658.             c = field[x + xx][y + yy];
  659.             if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  660.             {   creature[which].deltax = xx;
  661.                 creature[which].deltay = yy;
  662.             } else
  663.             {   creature[which].deltax = 0;
  664.                 creature[which].deltay = 0;
  665.         }   }
  666.         if
  667.         (   (creature[which].deltax || creature[which].deltay)
  668.          && (!arand(FREQ_CAMELDROP))
  669.         )
  670.         {   creature[which].last = creature[which].subspecies;
  671.         } else creature[which].last = EMPTY;
  672.     break;
  673.     case CLOUD:
  674.         if
  675.         (   creature[which].x == 0
  676.          || creature[which].x == fieldx
  677.          || field[x + creature[which].deltax][y + creature[which].deltay] == METAL
  678.          || field[x + creature[which].deltax][y + creature[which].deltay] == STONE
  679.          || field[x + creature[which].deltax][y + creature[which].deltay] == WOOD
  680.         )
  681.         {   creature[which].deltax = -creature[which].deltax;
  682.         }
  683.     break;
  684.     case DOG:
  685.         /* remove a movement from the dog queue */
  686.  
  687.         if (creature[which].dormant == CHASING)
  688.         {   if (creature[which].pos != -1)
  689.             {   creature[which].deltax = thedogqueue[which][0].deltax;
  690.                 creature[which].deltay = thedogqueue[which][0].deltay;
  691.                 if (--creature[which].pos != -1)
  692.                 {   for (i = 0; i <= creature[which].pos; i++)
  693.                     {   thedogqueue[which][i].deltax = thedogqueue[which][i + 1].deltax;
  694.                         thedogqueue[which][i].deltay = thedogqueue[which][i + 1].deltay;
  695.             }   }   }
  696.             else creature[which].alive = FALSE;
  697.         }
  698.     break;
  699.     case FISH:
  700.     do
  701.         {   xx = arand(2) - 1;
  702.             yy = arand(2) - 1;
  703.     } while (!valid(x + xx, y + yy));
  704.         c = field[x + xx][y + yy];
  705.         if
  706.         (   c == SLIME
  707.          || c == WOOD
  708.          || c == STONE
  709.          || c == METAL
  710.          || (c >= FIRSTTAIL && c <= LASTTAIL)
  711.          || (c >= FIRSTGLOW && c <= LASTGLOW)
  712.         )
  713.         {   creature[which].deltax = xx;
  714.             creature[which].deltay = yy;
  715.             creature[which].last = creature[which].oldlast;
  716.             if (c >= FIRSTTAIL && c <= LASTTAIL)
  717.             {   creature[which].oldlast = c - FIRSTTAIL + FIRSTGLOW;
  718.             } else creature[which].oldlast = c;
  719.         } else
  720.         {   creature[which].deltax =
  721.             creature[which].deltay = 0;
  722.         }
  723.     break;
  724.     case GOOSE:
  725.         i = arand(3);
  726.         switch(i)
  727.         {
  728.         case 0:
  729.             creature[which].deltax = -1;
  730.             creature[which].deltay = 0;
  731.         break;
  732.         case 1:
  733.             creature[which].deltax = 1;
  734.             creature[which].deltay = 0;
  735.         break;
  736.         case 2:
  737.             creature[which].deltax = 0;
  738.             creature[which].deltay = -1;
  739.         break;
  740.         case 3:
  741.             creature[which].deltax = 0;
  742.             creature[which].deltay = 1;
  743.         break;
  744.         default:
  745.         // assert(0);
  746.         break;
  747.         }
  748.     break;
  749.     case HORSE:
  750.         if (!arand(FREQ_HORSETURN))
  751.         {   if (!arand(1))
  752.             {    if (creature[which].dir == 0)
  753.                 {   creature[which].dir = 7;
  754.                 } else
  755.                 {   creature[which].dir--;
  756.         }    }
  757.             else
  758.             {    if (creature[which].dir == 7)
  759.                 {   creature[which].dir = 0;
  760.                 } else
  761.                 {   creature[which].dir++;
  762.             }    }
  763.  
  764.             turncreature(which);
  765.         }
  766.             break;
  767.     case KANGAROO:
  768.         creature[which].deltax = bsign(creature[which].deltax);
  769.         creature[which].deltay = bsign(creature[which].deltay);
  770.         if
  771.         (   ((!creature[which].deltax) && (!creature[which].deltay))
  772.          || !arand(FREQ_KANGAROOTURN)
  773.         )
  774.         {   do
  775.             {   xx = arand(2) - 1;
  776.                 yy = arand(2) - 1;
  777.             } while (!valid(x + xx, y + yy));
  778.             c = field[x + xx][y + yy];
  779.             if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  780.             {   creature[which].deltax = xx;
  781.                 creature[which].deltay = yy;
  782.             } else
  783.             {   creature[which].deltax = 0;
  784.                 creature[which].deltay = 0;
  785.         }   }
  786.         else
  787.         {   c = field[xwrap(x + creature[which].deltax)][ywrap(y + creature[which].deltay)];
  788.             if (c < FIRSTEMPTY || c > LASTEMPTY)
  789.             {   c = field[xwrap(x + (creature[which].deltax * 2))][ywrap(y + (creature[which].deltay * 2))];
  790.                 if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  791.                 {   creature[which].deltax *= 2;
  792.                     creature[which].deltay *= 2;
  793.                 } else
  794.                 {   c = field[xwrap(x - creature[which].deltax)][ywrap(y - creature[which].deltay)];
  795.                     if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  796.                     {   creature[which].deltax = -creature[which].deltax;
  797.                         creature[which].deltay = -creature[which].deltay;
  798.                     } else
  799.                     {   creature[which].deltax =
  800.                         creature[which].deltay = 0;
  801.         }   }   }   }
  802.     break;
  803.     case MISSILE_C:
  804.         bestdistance = 255;
  805.         for (player = 0; player <= 3; player++)
  806.         {   if (creature[which].player != player && worm[player].lives)
  807.             {   xx = abs(worm[player].x - x);
  808.                 yy = abs(worm[player].y - y);
  809.                 if (xx < yy)
  810.                 {   distance = xx;
  811.                 } else distance = yy;
  812.                 if (distance < bestdistance)
  813.                 {   bestdistance = distance;
  814.                     creature[which].deltax = bsign(worm[player].x - x);
  815.                     creature[which].deltay = bsign(worm[player].y - y);
  816.             }   }
  817.             for (i = 0; i <= CREATURES; i++)
  818.             {   if
  819.                 (   creature[i].alive
  820.                  && which != i
  821.                  && creature[i].player != player
  822.                 )
  823.                 {   xx = abs(creature[i].x - x);
  824.                     yy = abs(creature[i].y - y);
  825.                     if (xx < yy)
  826.                     {   distance = xx;
  827.                     } else distance = yy;
  828.                     if (distance < bestdistance)
  829.                     {   bestdistance = distance;
  830.                         creature[which].deltax = bsign(creature[i].x - x);
  831.                         creature[which].deltay = bsign(creature[i].y - y);
  832.         }   }   }   }
  833.         if (bestdistance == 255)
  834.         {   creature[which].alive = FALSE;
  835.             change(x, y, EMPTY);
  836.         }
  837.     break;
  838.     case MONKEY:
  839.         creature[which].pos += creature[which].dir;
  840.         if (creature[which].pos == 0) // monkey never stops moving
  841.         {   choosediagonal(which);
  842.             creature[which].dir = 1;
  843.         } elif (creature[which].pos == 5)
  844.         {   creature[which].deltax = -creature[which].deltax;
  845.             creature[which].deltay = -creature[which].deltay;
  846.             creature[which].dir = -1;
  847.         }
  848.     break;
  849.     case ORB:
  850.         frontx  = xwrap(x + creature[which].deltax);  /* look in front */
  851.         fronty  = ywrap(y + creature[which].deltay);
  852.         rearx   = xwrap(x - creature[which].deltax);  /* look behind */
  853.         reary   = ywrap(y - creature[which].deltay);
  854.         if (bouncecreature(which, frontx, fronty))
  855.         {   bounceoffcreature(which, frontx, fronty);
  856.             xx = -creature[which].deltax; /* default bounce angle is 180° */
  857.             yy = -creature[which].deltay;
  858.             if (!bouncecreature(which, frontx, reary))
  859.             {   if (bouncecreature(which, rearx, fronty))
  860.                 {   bounceoffcreature(which, rearx, fronty);
  861.                     xx = creature[which].deltax;
  862.             }   }
  863.             elif (!bouncecreature(which, rearx, fronty))
  864.             {   bounceoffcreature(which, rearx, fronty);
  865.                 yy = creature[which].deltay;
  866.             }
  867.             creature[which].deltax = xx;
  868.             creature[which].deltay = yy;
  869.         }
  870.     break;
  871.     case OTTER:
  872.         if (secondsleft)
  873.         {   return;
  874.         }
  875.         if (creature[which].journey == OTTER_RIGHT)
  876.         {   switch(creature[which].going)
  877.             {
  878.             case OTTER_DOWN:
  879.                 if (creature[which].y == fieldy)
  880.                 {   if (creature[which].x == fieldx)
  881.                     {   creature[which].journey = OTTER_LEFT;
  882.                         creature[which].going = OTTER_UP;
  883.                     } else
  884.                     {   creature[which].going = OTTER_RIGHT;
  885.                         creature[which].then  = OTTER_UP;
  886.                 }   }
  887.             break;
  888.             case OTTER_RIGHT:
  889.                 creature[which].going = creature[which].then;
  890.             break;
  891.             case OTTER_UP:             
  892.                 if (creature[which].y == 0)
  893.                 {   if (creature[which].x == fieldx)
  894.                     {   creature[which].journey = OTTER_LEFT;
  895.                         creature[which].going = OTTER_DOWN;
  896.                     } else
  897.                     {   creature[which].going = OTTER_RIGHT;
  898.                         creature[which].then  = OTTER_DOWN;
  899.                 }   }
  900.             break;
  901.             default:
  902.             break;
  903.         }   }
  904.         else
  905.         {   // assert(creature[which].journey == OTTER_LEFT);
  906.             switch(creature[which].going)
  907.             {
  908.             case OTTER_DOWN:
  909.                 if (creature[which].y == fieldy)
  910.                 {   if (creature[which].x == 0)
  911.                     {   creature[which].journey = OTTER_RIGHT;
  912.                         creature[which].going = OTTER_UP;
  913.                     } else
  914.                     {   creature[which].going = OTTER_LEFT;
  915.                         creature[which].then  = OTTER_UP;
  916.                 }   }
  917.             break;
  918.             case OTTER_LEFT:
  919.                 creature[which].going = creature[which].then;
  920.             break;
  921.             case OTTER_UP:             
  922.                 if (creature[which].y == 0)
  923.                 {   if (creature[which].x == 0)
  924.                     {   creature[which].journey = OTTER_RIGHT;
  925.                         creature[which].going = OTTER_DOWN;
  926.                     } else
  927.                     {   creature[which].going = OTTER_LEFT;
  928.                         creature[which].then  = OTTER_DOWN;
  929.                 }   }
  930.             break;
  931.             default:
  932.                 // assert(0);
  933.             break;
  934.         }   }
  935.  
  936.         if (creature[which].going == OTTER_RIGHT)
  937.         {   creature[which].deltax = 1;
  938.             creature[which].deltay = 0;
  939.         } elif (creature[which].going == OTTER_LEFT)
  940.         {   creature[which].deltax = -1;
  941.             creature[which].deltay = 0;
  942.         } elif (creature[which].going == OTTER_UP)
  943.         {   creature[which].deltax = 0;
  944.             creature[which].deltay = -1;
  945.         } elif (creature[which].going == OTTER_DOWN)
  946.         {   creature[which].deltax = 0;
  947.             creature[which].deltay = 1;
  948.         }
  949.     break;
  950.     case ANT:
  951.     do
  952.         {   xx = arand(2) - 1;
  953.             yy = arand(2) - 1;
  954.         } while (!valid(x + xx, y + yy));
  955.         if (xx == 0 && yy == 0)
  956.         {   if (valid(x + creature[which].deltax, y + creature[which].deltay))
  957.             {   xx = creature[which].deltax;
  958.                 yy = creature[which].deltay;
  959.             } else
  960.             {   xx = -creature[which].deltax;
  961.                 yy = -creature[which].deltay;
  962.         }   }
  963.         creature[which].deltax = xx;
  964.         creature[which].deltay = yy;
  965.     break;
  966.     case CYCLONE_C:
  967.         /* Cyclones have a slight upwards drift.
  968.         Higher values of WEIGHT make them less buoyant. */
  969.  
  970.         creature[which].deltax = arand(2) - 1;
  971.         if (!arand(WEIGHT))
  972.             creature[which].deltay = arand(1) - 1;
  973.         else creature[which].deltay = arand(2) - 1;
  974.     break;
  975.     case RABBIT:
  976.         xx = x + creature[which].deltax;
  977.         done = FALSE;
  978.         do
  979.         {    if (!valid(xx, y))
  980.             {   creature[which].alive = FALSE;
  981.                 change(x, y, EMPTY);
  982.                 done = TRUE;
  983.             } elif
  984.             (   field[xx][y] <= LASTOBJECT
  985.              || (field[xx][y] >= FIRSTEMPTY && field[xx][y] <= LASTEMPTY)
  986.              )
  987.             {   creature[which].x = xx;
  988.                 done = TRUE;
  989.              } else
  990.             {    xx += creature[which].deltax;
  991.         }   }
  992.         while (!done);
  993.     break;
  994.     case MOUSE:
  995.         bestdistance = 255;
  996.         if (x - DISTANCE_MOUSE < 0)
  997.         {    xmin = 0;
  998.         } else xmin = x - DISTANCE_MOUSE;
  999.         if (x + DISTANCE_MOUSE > fieldx)
  1000.         {    xmax = fieldx;
  1001.         } else xmax = x + DISTANCE_MOUSE;
  1002.         if (y - DISTANCE_MOUSE < 0)
  1003.         {    ymin = 0;
  1004.         } else ymin = y - DISTANCE_MOUSE;
  1005.         if (y + DISTANCE_MOUSE > fieldy)
  1006.         {    ymax = fieldy;
  1007.         } else ymax = y + DISTANCE_MOUSE;
  1008.  
  1009.         for (xx = xmin; xx <= xmax; xx++)
  1010.         {    for (yy = ymin; yy <= ymax; yy++)
  1011.             {    // assert(valid(xx, yy));
  1012.                 if (field[xx][yy] <= LASTOBJECT)
  1013.                 {    xxx = abs(xx - x);
  1014.                     yyy = abs(yy - y);
  1015.                     if (xxx < yyy)
  1016.                     {   distance = xxx;
  1017.                     } else distance = yyy;
  1018.                     if (distance < bestdistance)
  1019.                     {   bestdistance = distance;
  1020.                         creature[which].deltax = bsign(xx - x);
  1021.                         creature[which].deltay = bsign(yy - y);
  1022.         }    }   }    }
  1023.         if (bestdistance == 255)
  1024.         {   creature[which].deltax =
  1025.             creature[which].deltay = 0;
  1026.         }
  1027.     break;
  1028.     case SNAIL:
  1029.         xx = creature[which].deltax;
  1030.         yy = creature[which].deltay;
  1031.         if
  1032.         (   (!valid(x + xx, y + yy))
  1033.          || (xx == 0 && yy == 0)
  1034.          || (field[x + xx][y + yy] > LASTOBJECT && (field[x + xx][y + yy] < FIRSTEMPTY || field[x + xx][y + yy] > LASTEMPTY))
  1035.         )
  1036.         {   do
  1037.             {   xx = arand(2) - 1;
  1038.                 yy = arand(2) - 1;
  1039.             } while (!valid(x + xx, y + yy));
  1040.             if
  1041.             (    field[x + xx][y + yy] <= LASTOBJECT
  1042.              || (field[x + xx][y + yy] >= FIRSTEMPTY && field[x + xx][y + yy] <= LASTEMPTY)
  1043.              )
  1044.             {   creature[which].deltax = xx;
  1045.                 creature[which].deltay = yy;
  1046.             } else
  1047.             {   creature[which].deltax = 0;
  1048.                             creature[which].deltay = 0;
  1049.         }   }
  1050.     break;
  1051.     case SPIDER:
  1052.         xx = creature[which].deltax;
  1053.         yy = creature[which].deltay;
  1054.         if
  1055.         (   (!valid(x + xx, y + yy))
  1056.          || (xx == 0 && yy == 0)
  1057.          || (field[x + xx][y + yy] > LASTOBJECT && (field[x + xx][y + yy] < FIRSTEMPTY || field[x + xx][y + yy] > LASTEMPTY))
  1058.          || (!arand(FREQ_SPIDERTURN))
  1059.         )
  1060.         {   do
  1061.             {   xx = arand(2) - 1;
  1062.                 yy = arand(2) - 1;
  1063.             } while (!valid(x + xx, y + yy));
  1064.             if
  1065.             (   field[x + xx][y + yy] <= LASTOBJECT
  1066.              || (field[x + xx][y + yy] >= FIRSTEMPTY && field[x + xx][y + yy] <= LASTEMPTY)
  1067.              ||  field[x + xx][y + yy] == FROST // so that spiders can traverse their own webs
  1068.             )
  1069.             {   creature[which].deltax = xx;
  1070.                 creature[which].deltay = yy;
  1071.             } else
  1072.             {   creature[which].deltax = 0;
  1073.                 creature[which].deltay = 0;
  1074.         }   }
  1075.     break;
  1076.     case FROG:
  1077.         if (creature[which].deltax != 0 || creature[which].deltay != 0)
  1078.         {   creature[which].deltax = 0;
  1079.             creature[which].deltay = 0;
  1080.         } elif (creature[which].dormant == 0 && !arand(FREQ_FROGMOVE))
  1081.         {   xx = arand(6) - 3;
  1082.             yy = arand(6) - 3;
  1083.             if
  1084.             (   (xx != 0 || yy != 0)
  1085.              && valid(x + xx, y + yy)
  1086.              && field[x + xx][y + yy] >= FIRSTEMPTY
  1087.              && field[x + xx][y + yy] <= LASTEMPTY
  1088.             )
  1089.             {   creature[which].deltax = xx;
  1090.                 creature[which].deltay = yy;
  1091.                 if (!arand(1))
  1092.                 {   creature[which].dir = -1;
  1093.                 } else
  1094.                 {   creature[which].dir = 1;
  1095.         }   }   }
  1096.     break;
  1097.     case SALAMANDER:
  1098.         // this is a workaround for a very strange bug
  1099.         choosediagonal(which);
  1100.     break;
  1101.     default: // octopus, giraffe, fragment, bull
  1102.     break;
  1103.     }
  1104.  
  1105.     /* now move */
  1106.  
  1107.     if (creature[which].deltax || creature[which].deltay)
  1108.     {   if (creature[which].visible)
  1109.         {   /* erase previous image */
  1110.             if
  1111.             (   (creature[which].last >= FIRSTTAIL && creature[which].last <= LASTTAIL)
  1112.              || (creature[which].last >= FIRSTGLOW && creature[which].last <= LASTGLOW)                
  1113.             )
  1114.             {   field[x][y] = creature[which].last;
  1115.                 if (tailfield[x][y] < FIRSTMAGIC)
  1116.                 {   drawtail(x, y, tailfield[x][y] + ((creature[which].last - FIRSTGLOW) * SECONDMAGIC) + FIRSTMAGIC);
  1117.                 } else
  1118.                 {   drawtail(x, y, tailfield[x][y] + ((creature[which].last - FIRSTGLOW) * SECONDMAGIC));
  1119.             }   }
  1120.             else
  1121.             {   change(x, y, creature[which].last);
  1122.             }
  1123.             if (creature[which].species == OTTER)
  1124.             {   creature[which].last = STONE;
  1125.             } elif (creature[which].species == SPIDER)
  1126.             {   creature[which].last = FROST;
  1127.             } elif (creature[which].species == GOOSE)
  1128.             {   creature[which].last = GOLD;
  1129.             }  else
  1130.             {   creature[which].last = EMPTY;
  1131.         }   }
  1132.     if (creature[which].alive)
  1133.     {   creature[which].x += creature[which].deltax;
  1134.         creature[which].y += creature[which].deltay;
  1135.         if
  1136.             (   creature[which].species == ORB
  1137.              || creature[which].species == HORSE
  1138.              || creature[which].species == MONKEY
  1139.             )
  1140.         {   creature[which].x = xwrap(creature[which].x);
  1141.             creature[which].y = ywrap(creature[which].y);
  1142.             } elif (!valid(creature[which].x, creature[which].y))
  1143.             {   creature[which].alive = FALSE;
  1144.     }   }   }
  1145.  
  1146.     creature[which].visible = TRUE;
  1147.     x = creature[which].x;
  1148.     y = creature[which].y;
  1149.  
  1150.     /* Collision detection. */
  1151.  
  1152.     if
  1153.     (    creature[which].alive
  1154.      &&  creature[which].species != FISH
  1155.      &&  creature[which].species != GIRAFFE
  1156.      && (creature[which].deltax || creature[which].deltay)
  1157.     )
  1158.     {   c = field[x][y];
  1159.  
  1160.         if (c >= FIRSTHEAD && c <= LASTHEAD)
  1161.         {   wormcreature(c - FIRSTHEAD, which);
  1162.         } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  1163.         {   protcreature(c - FIRSTPROTECTOR, which);
  1164.         } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1165.         {   ;
  1166.         } elif
  1167.         (   (c >= FIRSTNUMBER && c <= LASTNUMBER)
  1168.          || (c >= FIRSTGRAVE  && c <= LASTGRAVE )
  1169.          ||  c == FROGTONGUE
  1170.          ||  c == START
  1171.         )
  1172.         {   creature[which].alive = FALSE;
  1173.         } elif (c >= FIRSTCREATURE)
  1174.         {   i = whichcreature(x, y, c, which);
  1175.             creaturecreature(which, i);
  1176.         } elif
  1177.         (   c == METAL
  1178.          || c == STONE
  1179.          || c == WOOD
  1180.         )
  1181.         {   if (!creatureinfo[creature[which].species - FIRSTCREATURE].wall)
  1182.             {   if (creature[which].species == FRAGMENT && c == METAL)
  1183.                 {   effect(FXUSE_ARMOUR);
  1184.                     reflect(which);
  1185.                 } elif
  1186.                 (   creature[which].species != OTTER
  1187.                  && creature[which].species != CYCLONE_C
  1188.                  && creature[which].species != ANT
  1189.                  && creature[which].species != MISSILE_C
  1190.                 )
  1191.                 {   creature[which].alive = FALSE;
  1192.         }   }   }
  1193.         elif (c == TELEPORT)
  1194.         {   i = whichteleport(x, y);
  1195.             if (blockedtel(i, creature[which].deltax, creature[which].deltay))
  1196.                 creature[which].alive = FALSE;
  1197.             else
  1198.             {   effect(FXUSE_TELEPORT);
  1199.                 creature[which].x = teleport[partner(i)].x + creature[which].deltax;
  1200.                 creature[which].y = teleport[partner(i)].y + creature[which].deltay;
  1201.  
  1202.                 if (creature[which].species == ORB)
  1203.                 {   creature[which].x = xwrap(creature[which].x);
  1204.                     creature[which].y = ywrap(creature[which].y);
  1205.                 } else
  1206.                 {   if (!(valid(creature[which].x, creature[which].y)))
  1207.                         creature[which].alive = FALSE;
  1208.                     if (creature[which].species == FRAGMENT)
  1209.                         creature[which].last = SILVER;
  1210.         }   }   }
  1211.         elif (c <= LASTOBJECT && creature[which].species != MOUSE)
  1212.         {   switch (c)
  1213.             {
  1214.             case MINIBOMB:
  1215.                 drawcreature(which);
  1216.                 bombblast(ORB, which, x, y, FALSE);
  1217.             break;
  1218.             case SUPERBOMB:
  1219.                 drawcreature(which);
  1220.                 bombblast(ORB, which, x, y, TRUE);
  1221.             break;
  1222.             case PROTECTOR:
  1223.                 effect(FXGET_OBJECT);
  1224.                 for (player = 0; player <= 3; player++)
  1225.                 {   if (worm[player].lives)
  1226.                     {   for (i = 0; i <= PROTECTORS; i++)
  1227.                         {  if (protector[player][i].alive)
  1228.                            {   protector[player][i].alive = FALSE;
  1229.                                if (protector[player][i].visible)
  1230.                                {   change(protector[player][i].x, protector[player][i].y, EMPTY);
  1231.                 }   }   }  }   }
  1232.             break;
  1233.             case MISSILE_O:
  1234.                 effect(FXGET_OBJECT);
  1235.                 for (i = 0; i <= CREATURES; i++)
  1236.                 {   if (creature[i].alive && creature[i].species == MISSILE_C)
  1237.                     {   creature[i].alive = FALSE;
  1238.                         change(x, y, EMPTY);
  1239.                 }   }
  1240.             break;
  1241.             case MULTIPLIER:
  1242.                 effect(FXGET_OBJECT);
  1243.                 for (player = 0; player <= 3; player++)
  1244.                 {   if (worm[player].lives)
  1245.                     {   worm[player].multi = 1;
  1246.                         stat(player, BONUS);
  1247.                 }   }
  1248.             break;
  1249.             case AFFIXER:
  1250.                 effect(FXGET_OBJECT);
  1251.                 for (player = 0; player <= 3; player++)
  1252.                     if (worm[player].lives)
  1253.                     {   worm[player].affixer = FALSE;
  1254.                         icon(player, AFFIXER);
  1255.                     }
  1256.             break;
  1257.             case REMNANTS:
  1258.                 effect(FXGET_OBJECT);
  1259.                 for (player = 0; player <= 3; player++)
  1260.                     if (worm[player].lives)
  1261.                     {   worm[player].remnants = FALSE;
  1262.                         icon(player, REMNANTS);
  1263.                     }
  1264.             break;
  1265.             case SIDESHOT:
  1266.                 effect(FXGET_POWERUP);
  1267.                 for (player = 0; player <= 3; player++)
  1268.                     if (worm[player].lives)
  1269.                     {   worm[player].sideshot = FALSE;
  1270.                         icon(player, SIDESHOT);
  1271.                     }
  1272.             break;
  1273.             case MAGNET:
  1274.                 effect(FXGET_OBJECT);
  1275.                 for (i = 0; i <= MAGNETS; i++)
  1276.                     if (magnet[i].alive)
  1277.                         magnet[i].alive = FALSE;
  1278.             break;
  1279.             case PUSHER:
  1280.                 effect(FXGET_OBJECT);
  1281.                 for (i = 0; i <= 3; i++)
  1282.                     if (worm[i].lives && worm[i].pusher)
  1283.                     {   worm[i].pusher = FALSE;
  1284.                         icon(i, PUSHER);
  1285.                     }
  1286.                 break;
  1287.             case ENCLOSER:
  1288.                 effect(FXGET_OBJECT);
  1289.                 for (i = 0; i <= 3; i++)
  1290.                 {   if (worm[i].lives && worm[i].encloser)
  1291.                     {   worm[i].encloser = FALSE;
  1292.                         icon(i, ENCLOSER);
  1293.                 }   }
  1294.             break;
  1295.             case GLOW:
  1296.                 effect(FXGET_OBJECT);
  1297.                 for (xx = 0; xx <= fieldx; xx++)
  1298.                     for (yy = 0; yy <= fieldy; yy++)
  1299.                         if (field[xx][yy] >= FIRSTGLOW && field[xx][yy] <= LASTGLOW)
  1300.                             change(xx, yy, EMPTY);
  1301.             break;
  1302.             case SWITCHER:
  1303.                 effect(FXGET_OBJECT);
  1304.                 for (xx = 0; xx <= fieldx; xx++)
  1305.                     for (yy = 0; yy <= fieldy; yy++)
  1306.                         if (field[xx][yy] >= FIRSTTAIL && field[xx][yy] <= LASTTAIL)
  1307.                             change(xx, yy, WOOD);
  1308.             break;
  1309.             case GROWER:
  1310.                 effect(FXGET_GROWER);
  1311.                 for (xx = 0; xx <= fieldx; xx++)
  1312.                     for (yy = 0; yy <= fieldy; yy++)
  1313.                         if (field[xx][yy] == WOOD)
  1314.                             for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  1315.                                 for (yyy = yy - 1; yyy <= yy + 1; yyy++)                                                                if (valid(xxx, yyy) && field[xxx][yyy] == EMPTY)
  1316.                                     field[xxx][yyy] = TEMPWOOD;
  1317.                 for (xx = 0; xx <= fieldx; xx++)
  1318.                     for (yy = 0; yy <= fieldy; yy++)
  1319.                         if (field[xx][yy] == TEMPWOOD)
  1320.                             change(xx, yy, WOOD);
  1321.             break;
  1322.             case AUTOJUMP:
  1323.                 effect(FXGET_OBJECT);
  1324.                 for (player = 0; player <= 3; player++)
  1325.                     if (worm[player].lives)
  1326.                     {   worm[player].autojump = FALSE;
  1327.                         icon(player, AUTOJUMP);
  1328.                     }
  1329.             break;
  1330.             case CUTTER:
  1331.                 effect(FXGET_OBJECT);
  1332.                 for (i = 0; i <= 3; i++)
  1333.                     if (worm[i].lives && worm[i].cutter)
  1334.                     {   worm[i].cutter = 0;
  1335.                         icon(i, CUTTER);
  1336.                     }
  1337.             break;
  1338.             default:
  1339.                 effect(FXGET_OBJECT);
  1340.                 creature[which].speed = speedup(creature[which].speed, FALSE);
  1341.             break;
  1342.     }   }   }
  1343.     
  1344.     x = creature[which].x; // These are refreshed in case a
  1345.     y = creature[which].y; // fragment has been reflected.
  1346.         
  1347.     if
  1348.     (   creature[which].alive
  1349.      && creature[which].visible
  1350.      && (creature[which].deltax || creature[which].deltay)
  1351.     )
  1352.     {   drawcreature(which);
  1353.     }
  1354.     
  1355.     if (creature[which].alive)
  1356.     {   /* decide whether to fire */
  1357.         switch(creature[which].species)
  1358.         {
  1359.         case CLOUD:
  1360.             if (!arand(FREQ_CLOUDFIRE))
  1361.             {   creaturebullet(x, y,  0, -1, FRAGMENT);
  1362.             }
  1363.             if (!arand(FREQ_CLOUDRAIN))
  1364.             {   if (creature[which].y != fieldy)
  1365.                 {   c = field[x][y + 1];
  1366.                     if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1367.                     {   for (i = 0; i <= CREATURES; i++)
  1368.                         {   if (!creature[i].alive)
  1369.                             {   createcreature(RAIN, i, x, y + 1, 0, 1, (UBYTE) ((r / 16) % 4), 0);
  1370.                                 break;
  1371.             }   }   }   }   }
  1372.         break;
  1373.         case KANGAROO:
  1374.             if (!arand(FREQ_KANGAROOFIRE))
  1375.             {   creaturebullet(x, y, -1, -1, FRAGMENT);
  1376.                 creaturebullet(x, y,  1, -1, FRAGMENT);
  1377.                 creaturebullet(x, y, -1,  1, FRAGMENT);
  1378.                 creaturebullet(x, y,  1,  1, FRAGMENT);
  1379.             }
  1380.         break;
  1381.         case MONKEY:
  1382.             if (creature[which].pos == 5)
  1383.             {   chooseorthagonal(&xx, &yy);
  1384.                 creaturebullet(x, y, xx, yy, BANANA);
  1385.             }
  1386.         break;
  1387.         case OCTOPUS:
  1388.             if (creature[which].dir == -1)
  1389.             {   if (!arand(FREQ_OCTOPUSFIRE))
  1390.                 {   creature[which].dir = arand(7);
  1391.                     if (arand(1))
  1392.                     {   creature[which].tonguedir = 1;
  1393.                     } else
  1394.                     {   creature[which].tonguedir = -1;
  1395.                     }
  1396.                     creature[which].pos = -1;
  1397.             }   }
  1398.             elif (!arand(FREQ_OCTOPUSSPIN))
  1399.             {   for (i = 0; i <= CREATURES; i++)
  1400.                 {   if
  1401.                     (   creature[i].alive
  1402.                      && creature[i].species == OCTOPUS
  1403.                      && creature[i].dir     >= 0
  1404.                     )
  1405.                     {   for (i = 0; i <= CREATURES; i++)
  1406.                         {   if (!creature[i].alive)
  1407.                             {   switch(creature[which].dir)
  1408.                                 {
  1409.                                 case 0:
  1410.                                     xx = 0;
  1411.                                     yy = -1;
  1412.                                 break;
  1413.                                 case 1:
  1414.                                     xx = 1;
  1415.                                     yy = -1;
  1416.                                 break;
  1417.                                 case 2:
  1418.                                     xx = 1;
  1419.                                     yy = 0;
  1420.                                 break;
  1421.                                 case 3:
  1422.                                     xx = 1;
  1423.                                     yy = 1;
  1424.                                 break;
  1425.                                 case 4:
  1426.                                     xx = 0;
  1427.                                     yy = 1;
  1428.                                 break;
  1429.                                 case 5:
  1430.                                     xx = -1;
  1431.                                     yy = 1;
  1432.                                 break;
  1433.                                 case 6:
  1434.                                     xx = -1;
  1435.                                     yy = 0;
  1436.                                 break;
  1437.                                 case 7:
  1438.                                     xx = -1;
  1439.                                     yy = -1;
  1440.                                 break;
  1441.                                 default:
  1442.                                     // assert(0);
  1443.                                     xx = yy = 0; // to avoid spurious warnings
  1444.                                 break;
  1445.                                 }
  1446.                                 xxx = x + xx;
  1447.                                 yyy = y + yy;
  1448.                                 if (valid(xxx, yyy))
  1449.                                 {   effect(FXBORN_FRAGMENT);
  1450.                                     createcreature(FRAGMENT, i, xxx, yyy, xx, yy, 255, FRAGMENT);
  1451.                                 }
  1452.                                 if (++creature[which].pos == 8)
  1453.                                 {   creature[which].pos = -1;
  1454.                                 } else
  1455.                                 {   if (creature[which].dir == 7 && creature[which].tonguedir == 1)
  1456.                                     {   creature[which].dir = 0;
  1457.                                     } elif (creature[which].dir == 0 && creature[which].tonguedir == -1)
  1458.                                     {   creature[which].dir = 7;
  1459.                                     } else
  1460.                                     {   creature[which].dir += creature[which].tonguedir;
  1461.                                 }   }
  1462.                                 break;
  1463.             }   }   }   }   }
  1464.         break;
  1465.         case SALAMANDER:
  1466.             if (!arand(FREQ_SALAMANDERFIRE))
  1467.             {   chooseorthagonal(&xx, &yy);
  1468.                 creaturebullet(x, y, xx, yy, FRAGMENT);
  1469.             }
  1470.         break;
  1471.         case FROG:
  1472.             if (creature[which].dormant == 0)
  1473.             {   if (!arand(FREQ_FROGFIRE))
  1474.                 {   creature[which].dormant = 1;
  1475.                     creature[which].tonguedir = 1;
  1476.                     creature[which].tonguex = x;
  1477.                     if (creature[which].dir == -1)
  1478.                     {   draw(x, y, FROGMOUTHLEFT);
  1479.                     } else
  1480.                     {   // assert(creature[which].dir == 1);
  1481.                         draw(x, y, FROGMOUTHRIGHT);
  1482.             }   }   }
  1483.             else
  1484.             {   creature[which].dormant += creature[which].tonguedir;
  1485.                 if (creature[which].tonguedir == 1)
  1486.                 {   if (valid(creature[which].tonguex + creature[which].dir, y))
  1487.                     {   c = field[creature[which].tonguex + creature[which].dir][y];
  1488.                         if
  1489.                         (    c != TELEPORT
  1490.                          &&  c != METAL
  1491.                          &&  c != STONE
  1492.                          &&  c != WOOD
  1493.                          && (c < FIRSTPROTECTOR || c > LASTPROTECTOR)
  1494.                         )
  1495.                         {   creature[which].tonguex += creature[which].dir;
  1496.                             if (c >= FIRSTCREATURE)
  1497.                             {   creature[whichcreature(creature[which].tonguex, y, c, which)].alive = FALSE;
  1498.                                 change(creature[which].tonguex, y, FROGTONGUE);
  1499.                             } elif (c >= FIRSTHEAD && c <= LASTHEAD && worm[c - FIRSTHEAD].armour == 0)
  1500.                             {   worm[c - FIRSTHEAD].cause = FROG;
  1501.                                 worm[c - FIRSTHEAD].alive = FALSE;
  1502.                                 worm[c - FIRSTHEAD].victor = -1;
  1503.                             } else
  1504.                             {   change(creature[which].tonguex, y, FROGTONGUE);
  1505.                         }   }
  1506.                         else
  1507.                         {   creature[which].tonguedir = -1;
  1508.                     }   }
  1509.                     else
  1510.                     {   creature[which].tonguedir = -1;
  1511.                 }   }
  1512.                 else
  1513.                 {   // assert(creature[which].tonguedir == -1);
  1514.                     if (creature[which].dormant > 1)
  1515.                     {   if (field[creature[which].tonguex][y] == FROGTONGUE)
  1516.                         {   change(creature[which].tonguex, y, EMPTY);
  1517.                         }
  1518.                         creature[which].tonguex -= creature[which].dir;
  1519.                     } else
  1520.                     {   if (creature[which].dir == -1)
  1521.                         {   draw(x, y, FROGLEFT);
  1522.                         } else
  1523.                         {   // assert(creature[which].dir == 1);
  1524.                             draw(x, y, FROGRIGHT);
  1525.             }   }   }   }
  1526.         break;
  1527.         default:
  1528.             // rabbits, snails, spiders, etc.
  1529.             // ie. creatures which do not fire
  1530.         break;
  1531. }   }   }
  1532.  
  1533. MODULE void creaturebullet(SBYTE x, SBYTE y, SBYTE deltax, SBYTE deltay, UBYTE subspecies)
  1534. {   UBYTE i, c;
  1535.  
  1536.     for (i = 0; i <= CREATURES; i++)
  1537.     {   if (!creature[i].alive)
  1538.         {   if (valid(x + deltax, y + deltay))
  1539.             {   c = field[x + deltax][y + deltay];
  1540.                 if
  1541.                 (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1542.                 ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1543.                 )
  1544.                 {   effect(FXBORN_FRAGMENT);
  1545.                     createcreature(FRAGMENT, i, x + deltax, y + deltay, deltax, deltay, 255, subspecies);
  1546.             }   }
  1547.             break;
  1548. }   }   }
  1549.  
  1550. AGLOBAL void wormkillcreature(UBYTE player, UBYTE which, FLAG vampirism)
  1551. {   FLAG novampirism = FALSE;
  1552.  
  1553.     /* rain and bananas are ineligible for vampirism
  1554.  
  1555.     if (which == 255)
  1556.     {   say("Attempted to kill invalid creature!", PURPLE);
  1557.         Delay(250);
  1558.         clearkybd();
  1559.         anykey(FALSE);
  1560.     }
  1561.     return; */
  1562.  
  1563.     if (creature[which].species == BANANA)
  1564.     {   if (creature[which].player == player)
  1565.         {   worm[player].lives += 2;
  1566.         } else
  1567.         {   worm[player].lives++;
  1568.         }
  1569.         stat(player, MINIHEALER);
  1570.     }
  1571.  
  1572.     if
  1573.     (   creature[which].species        == RAIN
  1574.      || (   creature[which].species    == FRAGMENT
  1575.          && creature[which].subspecies == BANANA
  1576.     )   )
  1577.     {   novampirism = TRUE;
  1578.         if (creature[which].player == player)
  1579.         {   wormscore(player, creature[which].score * 2);
  1580.         } else
  1581.         {   wormscore(player, creature[which].score);
  1582.     }   }
  1583.     else
  1584.     {   wormscore(player, creature[which].score);
  1585.     }
  1586.     creature[which].alive = FALSE;
  1587.     if (worm[player].lives && vampirism && !novampirism)
  1588.     {   worm[player].lives++;
  1589.         stat(player, MINIHEALER);
  1590.     }
  1591.  
  1592.     if (creature[which].species == FRAGMENT)
  1593.     {   if (creature[which].subspecies == BANANA)
  1594.         {   effect(FXGET_GROWER);
  1595.         } else
  1596.         {   // assert(creature[which].subspecies == FRAGMENT);
  1597.             effect(FXUSE_ARMOUR);
  1598.     }   }
  1599.     elif (creature[which].species == RAIN)
  1600.     {   effect(FXGET_RAIN);
  1601. }   }
  1602.  
  1603. AGLOBAL void protcreature(UBYTE player, UBYTE which)
  1604. {   /* Handles collisions between protectors and creatures. */
  1605.  
  1606.     switch(creature[which].species)
  1607.     {
  1608.     case FRAGMENT:
  1609.         effect(FXBORN_PROTECTOR);
  1610.         if (creature[which].subspecies == BANANA)
  1611.         {   wormkillcreature(player, which, TRUE);
  1612.         } else
  1613.         {   // assert(creature[which].subspecies == FRAGMENT);
  1614.             reflect(which);
  1615.         }
  1616.     break;
  1617.     case MISSILE_C:
  1618.         if (player != creature[which].player)
  1619.         {   effect(FXBORN_PROTECTOR);
  1620.             wormkillcreature(player, which, TRUE);
  1621.         } else creature[which].visible = FALSE;
  1622.     break;
  1623.     default:
  1624.         effect(FXBORN_PROTECTOR);
  1625.         wormkillcreature(player, which, TRUE);
  1626.     break;
  1627. }   }
  1628.  
  1629. AGLOBAL void wormcreature(UBYTE player, UBYTE which)
  1630. {   SBYTE xx, yy;
  1631.  
  1632.     /* Handles collisions between worms and creatures. */
  1633.  
  1634.     if (creature[which].species == GIRAFFE)
  1635.     {   xx = worm[player].x - (worm[player].deltax * DISTANCE_GIRAFFE);
  1636.         yy = worm[player].y - (worm[player].deltay * DISTANCE_GIRAFFE);
  1637.  
  1638.         if
  1639.         (   valid(xx, yy)
  1640.          && !blockedsquare(xx, yy)
  1641.         )
  1642.         {   worm[player].deltax = -worm[player].deltax;
  1643.             worm[player].deltay = -worm[player].deltay;
  1644.             worm[player].x = xx;
  1645.             worm[player].y = yy;
  1646.  
  1647.             if (!worm[player].armour)
  1648.             {   worm[player].alive  = FALSE;
  1649.                 worm[player].cause  = GIRAFFE;
  1650.                 worm[player].victor = -1;
  1651.             }
  1652.  
  1653.             return;
  1654.     }   }
  1655.  
  1656.     if
  1657.     (   creature[which].species == DOG
  1658.      && creature[which].dormant == DORMANT
  1659.     )
  1660.     {   effect(FXBORN_DOG);
  1661.         creature[which].dormant = AWAKENING;
  1662.         creature[which].player  = player;
  1663.         worm[player].last       = DOG;
  1664.         return;
  1665.     }
  1666.  
  1667.     if
  1668.     (   creature[which].species == MISSILE_C
  1669.      && creature[which].player == player
  1670.     )
  1671.     {   creature[which].visible = FALSE;
  1672.         return;
  1673.     }
  1674.  
  1675.     if
  1676.     (   creature[which].species == FRAGMENT
  1677.      && creature[which].subspecies == FRAGMENT
  1678.      && worm[player].armour
  1679.     )
  1680.     {   effect(FXUSE_ARMOUR);
  1681.         if (creature[which].species == FRAGMENT)
  1682.         {   reflect(which);
  1683.         }
  1684.         return;
  1685.     }
  1686.  
  1687.     wormkillcreature(player, which, TRUE);
  1688.  
  1689.     if (creature[which].species == RAIN)
  1690.     {   return;
  1691.     }
  1692.     if
  1693.     (   creature[which].species == FRAGMENT
  1694.      && creature[which].subspecies == BANANA
  1695.     )
  1696.     {   return;
  1697.     }
  1698.     
  1699.     if (worm[player].armour)
  1700.     {   effect(FXUSE_ARMOUR);
  1701.     } elif (creature[which].player != player)
  1702.     {   if (creature[which].species == MISSILE_C)
  1703.         {   worm[player].cause = FIRSTMISSILE + creature[which].player;
  1704.         } else
  1705.         {   worm[player].cause = creature[which].species;
  1706.         }
  1707.         worm[player].victor = creature[which].player;
  1708.         worm[player].alive = FALSE;
  1709. }   }
  1710.  
  1711. MODULE void creaturecreature(UBYTE which1, UBYTE which2)
  1712. {   if
  1713.     (   creature[which1].species == MISSILE_C
  1714.      && creature[which2].species != MISSILE_C
  1715.     )
  1716.     {   wormkillcreature(creature[which1].player, which2, TRUE);
  1717.     } elif
  1718.     (   creature[which1].species != MISSILE_C
  1719.      && creature[which2].species == MISSILE_C
  1720.     )
  1721.     {   wormkillcreature(creature[which2].player, which1, TRUE);
  1722.     } else
  1723.     {   creature[which1].alive =
  1724.         creature[which2].alive = FALSE;
  1725.         change(creature[which1].x, creature[which1].y, BONUS);
  1726. }   }
  1727.  
  1728. MODULE void bounceoffcreature(UBYTE which, SBYTE x, SBYTE y)
  1729. {   if
  1730.     (   field[x][y] >= FIRSTCREATURE
  1731.      && creatureinfo[field[x][y] - FIRSTCREATURE].wall
  1732.     )
  1733.     {   creature[whichcreature(x, y, field[x][y], which)].alive = FALSE;
  1734.         change(x, y, BONUS);
  1735. }   }
  1736.  
  1737. MODULE ABOOL bouncecreature(UBYTE which, SBYTE x, SBYTE y)
  1738. {   if
  1739.     (    field[x][y] == METAL
  1740.      ||  field[x][y] == STONE
  1741.      ||  field[x][y] == WOOD
  1742.      || (field[x][y] >= FIRSTCREATURE && creatureinfo[field[x][y] - FIRSTCREATURE].wall)
  1743.      || (field[x][y] >= FIRSTTAIL && field[x][y] <= LASTTAIL)
  1744.      || (field[x][y] >= FIRSTGLOW && field[x][y] <= LASTGLOW)
  1745.     )
  1746.     {   return TRUE;
  1747.     } else
  1748.     {   return FALSE;
  1749. }   }
  1750.  
  1751. AGLOBAL UBYTE whichcreature(SBYTE x, SBYTE y, UBYTE species, UBYTE exception)
  1752. {   UBYTE i;    
  1753.  
  1754.     for (i = 0; i <= CREATURES; i++)
  1755.     {   if
  1756.         (   creature[i].alive
  1757.          && creature[i].x       == x
  1758.          && creature[i].y       == y
  1759.          && creature[i].species == species
  1760.          && i                   != exception
  1761.         )
  1762.         {   return i;
  1763.     }   }
  1764.  
  1765. /*  say("Attempted to find invalid creature!", PURPLE);
  1766.     Delay(250);
  1767.     clearkybd();
  1768.     anykey(FALSE); */
  1769.  
  1770.     return 255; /* error code */
  1771. }
  1772.  
  1773. AGLOBAL void wormloop(SBYTE player)
  1774. {   SBYTE bestx = 0, besty = 0, // to avoid spurious warnings
  1775.           dirx, diry, i, j, x, y, index1, index2;
  1776.     SWORD bestgood, good;
  1777.     UBYTE c;
  1778.  
  1779.    /*  Amiga worm control
  1780.        Remove a keystroke from the worm queue
  1781.        Move worm (and add a keystroke to the dog queue)
  1782.        Check for enclosure
  1783.        Move protectors
  1784.        Collision detection
  1785.  
  1786.     AI: Amiga worm control.
  1787.  
  1788.     Worm checks ahead, left and right one square. Assigns opinions
  1789.     to those three choices and then takes the appropriate one.
  1790.  
  1791.     Things which slow the worm down are doubly feared; this is to avoid
  1792.     endless ramming situations. */
  1793.  
  1794.     if (worm[player].control == AMIGA)
  1795.     {   if (!arand(50))
  1796.             wormqueue(player, arand(2) - 1, arand(2) - 1);
  1797.         else
  1798.         {   bestgood = -128;
  1799.  
  1800.             for (i = 0; i <= 8; i++)
  1801.             {   switch(i % 3)
  1802.                 {
  1803.                 case 0:
  1804.                     dirx = -1;
  1805.                 break;
  1806.                 case 1:
  1807.                     dirx = 0;
  1808.                 break;
  1809.                 case 2:
  1810.                     dirx = 1;
  1811.                 break;
  1812.                 default:
  1813.                     // assert(0);
  1814.                 break;
  1815.                 }
  1816.                 switch(i / 3)
  1817.                 {
  1818.                 case 0:
  1819.                     diry = -1;
  1820.                 break;
  1821.                 case 1:
  1822.                     diry = 0;
  1823.                 break;
  1824.                 case 2:
  1825.                     diry = 1;
  1826.                 break;
  1827.                 default:
  1828.                     // assert(0);
  1829.                 break;
  1830.                 }
  1831.                 if
  1832.                 (   (   dirx == -worm[player].deltax
  1833.                      && diry == -worm[player].deltay
  1834.                     )
  1835.                  || (   dirx == 0
  1836.                      && diry == 0
  1837.                 )   )
  1838.                 {   continue;
  1839.                 }
  1840.  
  1841.                 c = field[xwrap(worm[player].x + dirx)][ywrap(worm[player].y + diry)];
  1842.                 if (c >= FIRSTNUMBER && c <= LASTNUMBER)
  1843.                     good = POINTS_LETTER;
  1844.                 elif (c >= FIRSTHEAD && c <= LASTHEAD)
  1845.                     good = -(PAIN_HEAD);
  1846.                 elif (c <= LASTOBJECT)
  1847.                     good = (SWORD) object[c].score;
  1848.                 elif (c == FIRSTPROTECTOR + player)
  1849.                     good = POINTS_EMPTY;
  1850.                 elif (c >= FIRSTGLOW && c <= LASTGLOW)
  1851.                 {   if (player == c - FIRSTGLOW)
  1852.                         good = -1;
  1853.                     else good = -(PAIN_GLOW);
  1854.                 } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  1855.                 {   good = POINTS_GRAVE;
  1856.                 } elif (c >= FIRSTCHERRY && c <= LASTCHERRY)
  1857.                 {   good = POINTS_CHERRY; // should really be 2x if friendly
  1858.                 } elif (c >= FIRSTFLOWER && c <= LASTFLOWER)
  1859.                 {   good = POINTS_FLOWER; // should really be 2x if friendly
  1860.                 } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1861.                 {   if (worm[player].armour > 10)
  1862.                         if (player != c - FIRSTTAIL)
  1863.                             good = 2;
  1864.                         else good = 0;
  1865.                     elif (player == c - FIRSTTAIL)
  1866.                         good = -(PAIN_FRIENDLYTAIL);
  1867.                     else good = -(PAIN_ENEMYTAIL);
  1868.                 } else switch(c)
  1869.                 {
  1870.                 case GOLD:
  1871.                     good = POINTS_GOLD;
  1872.                 break;
  1873.                 case SILVER:
  1874.                     good = POINTS_SILVER;
  1875.                 break;
  1876.                 case EMPTY:
  1877.                     good = POINTS_EMPTY;
  1878.                 break;
  1879.                 case DYNAMITE:
  1880.                     good = 1;
  1881.                 break;
  1882.                 case SLIME:
  1883.                     if (worm[player].armour > 0)
  1884.                         good = 0;
  1885.                     else good = -(PAIN_SLIME);
  1886.                 break;
  1887.                 case WOOD:
  1888.                     good = -(PAIN_WOOD  * 3);
  1889.                 break;
  1890.                 case STONE:
  1891.                     good = -(PAIN_STONE * 3);
  1892.                 break;
  1893.                 case METAL:
  1894.                     good = -(PAIN_METAL * 3);
  1895.                 break;
  1896.                 case START:
  1897.                     good = POINTS_LETTER * 2;
  1898.                 break;
  1899.                 default:
  1900.                     if (c >= FIRSTCREATURE)
  1901.                     {   if (creature[whichcreature(xwrap(worm[player].x + dirx), ywrap(worm[player].y + diry), c, 255)].player == player)
  1902.                         {   good = creatureinfo[c - FIRSTCREATURE].score;
  1903.                         } elif (creatureinfo[c - FIRSTCREATURE].wall)
  1904.                         {   good = -(PAIN_CREATURE * 2);
  1905.                         } else good = -PAIN_CREATURE;
  1906.                     } else
  1907.                     {   // eg. frost, arrows
  1908.                         good = 0;
  1909.                     }
  1910.                 break;
  1911.                 }
  1912.                 if
  1913.                 (   good > bestgood
  1914.                  || (good == bestgood && dirx == worm[player].deltax && diry == worm[player].deltay)
  1915.                 )
  1916.                 {   bestx = dirx;
  1917.                     besty = diry;
  1918.                     bestgood = good;
  1919.             }   }
  1920.             if (bestgood < -2 && !arand(1))
  1921.             {   // turn in any of the 8 directions, or fire
  1922.                 wormqueue
  1923.                 (   player,
  1924.                     (SBYTE) ((arand(1) * 2) - 1),
  1925.                     (SBYTE) ((arand(1) * 2) - 1)
  1926.                 );
  1927.             }
  1928.             if (bestgood < 0 && !arand(2))
  1929.                 wormqueue(player, 0, 0);
  1930.             elif (bestx != worm[player].deltax || besty != worm[player].deltay)
  1931.                 wormqueue(player, bestx, besty);
  1932.     }   }
  1933.  
  1934.     /* remove a keystroke from the worm queue */
  1935.  
  1936.     if (worm[player].pos != -1)                         
  1937.     {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  1938.             wormbullet(player);
  1939.         else
  1940.         {   if (!worm[player].frosted)
  1941.             {   turnworm(player, thewormqueue[player][0].deltax, thewormqueue[player][0].deltay);
  1942.         }   }
  1943.         if (--worm[player].pos != -1)
  1944.         {   for (i = 0; i <= worm[player].pos; i++)
  1945.             {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  1946.                 thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  1947.     }   }   }
  1948.     worm[player].frosted = FALSE;
  1949.  
  1950.     /* move worm */
  1951.  
  1952.     if (!worm[player].speed)
  1953.     {    return;
  1954.     }
  1955.     
  1956.     if (worm[player].last == FIRSTTAIL + player)
  1957.     {    field[worm[player].x][worm[player].y] = FIRSTTAIL + player;
  1958.         index1 =       worm[player].olddeltax + 1 + (      (worm[player].olddeltay + 1) * 3);
  1959.         index2 = bsign(worm[player].deltax)   + 1 + ((bsign(worm[player].deltay)   + 1) * 3);
  1960.         drawtail(worm[player].x, worm[player].y, eachtail[player][0][index1][index2]);
  1961.     } elif (worm[player].last == FIRSTGLOW + player)
  1962.     {   field[worm[player].x][worm[player].y] = FIRSTGLOW + player;
  1963.         index1 =       worm[player].olddeltax + 1 + (      (worm[player].olddeltay + 1) * 3);
  1964.         index2 = bsign(worm[player].deltax)   + 1 + ((bsign(worm[player].deltay)   + 1) * 3);
  1965.         drawtail(worm[player].x, worm[player].y, eachtail[player][1][index1][index2]);
  1966.     } else
  1967.     {   change(worm[player].x, worm[player].y, worm[player].last);
  1968.     }
  1969.  
  1970.     worm[player].x = xwrap(worm[player].x + worm[player].deltax);
  1971.     worm[player].y = ywrap(worm[player].y + worm[player].deltay);
  1972.  
  1973.     if (worm[player].glow)
  1974.     {   worm[player].last = FIRSTGLOW + player;
  1975.     } else
  1976.     {   worm[player].last = FIRSTTAIL + player;
  1977.     }
  1978.  
  1979.     for (i = 0; i <= CREATURES; i++)
  1980.     {   if
  1981.         (   creature[i].alive
  1982.          && creature[i].species == DOG
  1983.          && creature[i].dormant >  DORMANT
  1984.          && creature[i].player  == player
  1985.         )
  1986.         {   if (!worm[player].rammed)
  1987.                 dogqueue(i, worm[player].deltax, worm[player].deltay);
  1988.             if (creature[i].dormant < CHASING)
  1989.             {   creature[i].dormant++;
  1990.                 drawcreature(i);
  1991.     }   }   }
  1992.  
  1993.     /* The deltas are not changed back to the range of -1..1 until after
  1994.     the dogs have looked at the queue. This enables them to jump properly. */
  1995.  
  1996.     worm[player].rammed = FALSE;
  1997.     worm[player].deltax = bsign(worm[player].deltax);
  1998.     worm[player].deltay = bsign(worm[player].deltay);
  1999.     worm[player].olddeltax = worm[player].deltax;
  2000.     worm[player].olddeltay = worm[player].deltay;
  2001.  
  2002.     /*  check for enclosure
  2003.         #####
  2004.         #...#
  2005.         #...# . = interior
  2006.         #...# # = tail
  2007.         ####! ! = head */
  2008.  
  2009.     enclosed = FALSE;
  2010.     for (i = ENCLOSURE_MIN; i <= ENCLOSURE_MAX; i++) // for each size of interior
  2011.     {   for (j = 0; j <= 3; j++) // four times, once for each direction
  2012.         {   checkrectangle(j, player, i, i);
  2013.             if (worm[player].encloser)
  2014.             {   checkrectangle(j, player, i, i + 1);
  2015.                 checkrectangle(j, player, i + 1, i);
  2016.     }   }   }
  2017.  
  2018.     protectorloop1(player);
  2019.  
  2020.     // head collision detection
  2021.     wormcol(player, worm[player].x, worm[player].y);
  2022.     // draw head
  2023.     field[worm[player].x][worm[player].y] = FIRSTHEAD + player;
  2024.     drawhead(player);
  2025.  
  2026.     updatearrow(worm[player].arrowy);
  2027.     worm[player].arrowy = worm[player].y;
  2028.     updatearrow(worm[player].arrowy);
  2029.  
  2030.     protectorloop2(player);
  2031.     
  2032.     if (worm[player].cutter)
  2033.     {   // straight ahead
  2034.         x = xwrap(worm[player].x + worm[player].deltax);
  2035.         y = ywrap(worm[player].y + worm[player].deltay);
  2036.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2037.         // left
  2038.         if (!worm[player].deltax || !worm[player].deltay)
  2039.         {   // if orthagonal
  2040.             x = xwrap(worm[player].x + worm[player].deltay);
  2041.             y = ywrap(worm[player].y - worm[player].deltax);
  2042.         } else // diagonal
  2043.         {   if (worm[player].deltax == worm[player].deltay)
  2044.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2045.                 y = ywrap(worm[player].y - worm[player].deltay);
  2046.             } else
  2047.             {   x = xwrap(worm[player].x - worm[player].deltax);
  2048.                 y = ywrap(worm[player].y + worm[player].deltay);
  2049.         }   }
  2050.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2051.         // right
  2052.         if (!worm[player].deltax || !worm[player].deltay)
  2053.         {   // if orthagonal
  2054.             x = xwrap(worm[player].x - worm[player].deltay);
  2055.             y = ywrap(worm[player].y + worm[player].deltax);
  2056.         } else // diagonal
  2057.         {   if (worm[player].deltax == worm[player].deltay)
  2058.             {   x = xwrap(worm[player].x - worm[player].deltax);
  2059.                 y = ywrap(worm[player].y + worm[player].deltay);
  2060.             } else
  2061.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2062.                 y = ywrap(worm[player].y - worm[player].deltay);
  2063.         }   }
  2064.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2065.         // ahead left
  2066.         if (!worm[player].deltax || !worm[player].deltay)
  2067.         {   // if orthagonal
  2068.             if (worm[player].deltax) // if east or west
  2069.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2070.                 y = ywrap(worm[player].y - worm[player].deltax);
  2071.             } else // north or south
  2072.             {   x = xwrap(worm[player].x + worm[player].deltay);
  2073.                 y = ywrap(worm[player].y + worm[player].deltay);
  2074.         }   }
  2075.         else // diagonal
  2076.         {   if (worm[player].deltax == worm[player].deltay)
  2077.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2078.                 y = worm[player].y;
  2079.             } else
  2080.             {   x = worm[player].x;
  2081.                 y = ywrap(worm[player].y + worm[player].deltay);
  2082.         }   }
  2083.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2084.         // ahead right
  2085.         if (!worm[player].deltax || !worm[player].deltay)
  2086.         {   // if orthagonal
  2087.             if (worm[player].deltax) // if east or west
  2088.             {   x = xwrap(worm[player].x + worm[player].deltax);;
  2089.                 y = ywrap(worm[player].y + worm[player].deltax);
  2090.             } else // north or south
  2091.             {   x = xwrap(worm[player].x - worm[player].deltay);
  2092.                 y = ywrap(worm[player].y + worm[player].deltay);
  2093.         }   }
  2094.         else // diagonal
  2095.         {   if (worm[player].deltax == worm[player].deltay)
  2096.             {   x = worm[player].x;
  2097.                 y = ywrap(worm[player].y + worm[player].deltay);
  2098.             } else
  2099.             {   x = xwrap(worm[player].x + worm[player].deltax);
  2100.                 y = worm[player].y;
  2101.         }   }
  2102.         squareblast(HEAD, player, field[x][y], x, y, TRUE, FALSE);
  2103. }   }
  2104.  
  2105. MODULE void protcol(SBYTE player, SBYTE x, SBYTE y, SBYTE thisprot)
  2106. {   UBYTE c = field[x][y];
  2107.     SBYTE i;
  2108.  
  2109.     if (c == EMPTY)
  2110.     {   ;
  2111.     } elif (c >= FIRSTHEAD && c <= LASTHEAD)
  2112.     {   protworm(x, y, player, c - FIRSTHEAD);
  2113.     } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  2114.     {   protprot(x, y, player, c - FIRSTPROTECTOR);
  2115.     } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  2116.     {   if (player == c - FIRSTTAIL)
  2117.         {   protector[player][thisprot].visible = FALSE;
  2118.     }   }
  2119.     elif
  2120.     (   c == STONE
  2121.      || c == WOOD
  2122.      || c == METAL
  2123.      || c == TELEPORT
  2124.      || c == FIRSTGLOW + player
  2125.      || c == START
  2126.     )
  2127.     {   protector[player][thisprot].visible = FALSE;
  2128.     } elif (c >= FIRSTCREATURE)
  2129.     {   i = whichcreature(x, y, c, 255);
  2130.         protcreature(player, i);
  2131.     } else
  2132.     {   bothcol(player, x, y);
  2133. }   }
  2134.  
  2135. AGLOBAL void bothcol(SBYTE player, SBYTE x, SBYTE y)
  2136. {   UBYTE c = field[x][y], i;
  2137.  
  2138.     if (c >= FIRSTNUMBER && c <= LASTNUMBER)
  2139.     {   if (!(getnumber(player)))
  2140.         {   putnumber();
  2141.     }   }
  2142.     elif (c >= FIRSTFLOWER && c <= LASTFLOWER)
  2143.     {   effect(FXGET_GRAVE);
  2144.         if (player == c - FIRSTFLOWER)
  2145.         {   wormscore(player, POINTS_FLOWER * 2);
  2146.         } else
  2147.         {   wormscore(player, POINTS_FLOWER);
  2148.         }
  2149.         if (level != 0)
  2150.         {   getnumber(player);
  2151.             change(numberx, numbery, FIRSTNUMBER + number - 1);
  2152.             updatearrow(numbery);
  2153.     }   }
  2154.     elif (c >= FIRSTCHERRY && c <= LASTCHERRY)
  2155.     {   effect(FXGET_GRAVE);
  2156.         if (player == c - FIRSTCHERRY)
  2157.         {   wormscore(player, POINTS_CHERRY * 2);
  2158.         } else
  2159.         {   wormscore(player, POINTS_CHERRY);
  2160.     }   }
  2161.     elif (c <= LASTOBJECT)
  2162.     {   wormscore(player, wormobject(player, x, y));
  2163.     } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  2164.     {   effect(FXGET_GRAVE);
  2165.         wormscore(player, POINTS_GRAVE);
  2166.  
  2167.         worm[player].multi *= worm[c - FIRSTGRAVE].multi;
  2168.         if (worm[player].multi > 1)
  2169.         {   if (worm[player].multi > MULTILIMIT)
  2170.                 worm[player].multi = MULTILIMIT;
  2171.         }
  2172.         worm[player].power += worm[c - FIRSTGRAVE].power;
  2173.         if (worm[player].power > 1)
  2174.         {   if (worm[player].power > POWERLIMIT)
  2175.                 worm[player].power = POWERLIMIT;
  2176.             stat(player, POWER);
  2177.             worm[c - FIRSTGRAVE].power = 0;
  2178.             stat(c - FIRSTGRAVE, POWER);
  2179.         }
  2180.         worm[player].ammo += worm[c - FIRSTGRAVE].ammo;
  2181.         if (worm[player].ammo > 0)
  2182.         {   if (worm[player].ammo > AMMOLIMIT)
  2183.                 worm[player].ammo = AMMOLIMIT;
  2184.             stat(player, AMMO);
  2185.             worm[c - FIRSTGRAVE].ammo = 0;
  2186.             stat(c - FIRSTGRAVE, AMMO);
  2187.         }
  2188.         if (worm[c - FIRSTGRAVE].brakes)
  2189.         {   worm[player].brakes = TRUE;
  2190.             stat(player, BRAKES);
  2191.             worm[c - FIRSTGRAVE].brakes = FALSE;
  2192.             worm[c - FIRSTGRAVE].speed = NORMAL;
  2193.             stat(c - FIRSTGRAVE, BRAKES);
  2194.         }
  2195.         if (worm[c - FIRSTGRAVE].affixer)
  2196.         {   worm[player].affixer = TRUE;
  2197.             worm[c - FIRSTGRAVE].affixer = FALSE;
  2198.         }
  2199.         if (worm[c - FIRSTGRAVE].remnants)
  2200.         {   worm[player].remnants = TRUE;
  2201.             worm[c - FIRSTGRAVE].remnants = FALSE;
  2202.         }
  2203.         if (worm[c - FIRSTGRAVE].sideshot)
  2204.         {   worm[player].sideshot = TRUE;
  2205.             worm[c - FIRSTGRAVE].sideshot = FALSE;
  2206.         }
  2207.         if (worm[c - FIRSTGRAVE].pusher)
  2208.         {   worm[player].pusher = TRUE;
  2209.             worm[c - FIRSTGRAVE].pusher = FALSE;
  2210.         }
  2211.         if (worm[c - FIRSTGRAVE].encloser)
  2212.         {   worm[player].encloser = TRUE;
  2213.             worm[c - FIRSTGRAVE].encloser = FALSE;
  2214.         }
  2215.         if (worm[c - FIRSTGRAVE].autojump)
  2216.         {   worm[player].autojump = TRUE;
  2217.             worm[c - FIRSTGRAVE].autojump = FALSE;
  2218.         }
  2219.  
  2220.         if (worm[c - FIRSTGRAVE].armour)
  2221.         {   worm[player].armour += worm[c - FIRSTGRAVE].armour;
  2222.             if (worm[player].armour > ARMOURLIMIT)
  2223.                 worm[player].armour = ARMOURLIMIT;
  2224.             worm[c - FIRSTGRAVE].armour = 0;
  2225.         }
  2226.         if (worm[c - FIRSTGRAVE].glow)
  2227.         {   worm[player].glow += worm[c - FIRSTGRAVE].glow;
  2228.             if (worm[player].glow > GLOWLIMIT)
  2229.                 worm[player].glow = GLOWLIMIT;
  2230.             worm[c - FIRSTGRAVE].glow = 0;
  2231.         }
  2232.         if (worm[c - FIRSTGRAVE].cutter)
  2233.         {   worm[player].cutter += worm[c - FIRSTGRAVE].cutter;
  2234.             if (worm[player].armour > CUTTERLIMIT)
  2235.                 worm[player].armour = CUTTERLIMIT;
  2236.             worm[c - FIRSTGRAVE].cutter = 0;
  2237.         }
  2238.  
  2239.         for (i = 0; i <= LASTOBJECT; i++)
  2240.         {   icon(player, i);
  2241.             icon(c - FIRSTGRAVE, i);
  2242.     }   }
  2243.     else
  2244.     {   switch(c)
  2245.         {
  2246.         case SILVER:
  2247.             wormscore(player, POINTS_SILVER);
  2248.         break;
  2249.         case GOLD:
  2250.             wormscore(player, POINTS_GOLD);
  2251.         break;
  2252.         case DYNAMITE:
  2253.             effect(FXUSE_BOMB);
  2254.             banging = TRUE;
  2255.             bangdynamite(x, y, player);
  2256.         break;
  2257.         default:
  2258.         break;
  2259. }   }   } 
  2260.  
  2261. MODULE void wormbullet(SBYTE player)
  2262. {   ABOOL finished,
  2263.           numbered = FALSE;
  2264.     FLAG  final;
  2265.     SBYTE distance,
  2266.           i, j,
  2267.           x, y;
  2268.     UBYTE c;
  2269.  
  2270.     if (!worm[player].ammo)
  2271.     {   stat(player, BONUS); // why?
  2272.         if (worm[player].speed == FAST)
  2273.             distance = DISTANCE_FAST;
  2274.         elif (worm[player].speed == NORMAL)
  2275.             distance = DISTANCE_NORMAL;
  2276.         else
  2277.         {   // assert(worm[player].speed == SLOW);
  2278.             distance = DISTANCE_SLOW;
  2279.         }
  2280.  
  2281.         // assert(abs(worm[player].deltax) <= 1 && abs(worm[player].deltay) <= 1);
  2282.         x = xwrap(worm[player].x + (worm[player].deltax * distance));
  2283.         y = ywrap(worm[player].y + (worm[player].deltay * distance));
  2284.         c = field[x][y];
  2285.  
  2286.         if
  2287.         (   (c < FIRSTGLOW || c > LASTGLOW || player != c - FIRSTGLOW)
  2288.          && (!blockedsquare(x, y))
  2289.         )
  2290.         {   worm[player].deltax *= distance;
  2291.             worm[player].deltay *= distance;
  2292.     }   }
  2293.     else
  2294.     {   effect(FXUSE_AMMO);
  2295.         worm[player].ammo--;
  2296.         stat(player, AMMO);
  2297.         if (worm[player].sideshot)
  2298.         {   bullet[7].alive      = bullet[8].alive      = TRUE;
  2299.             bullet[7].teleported = bullet[8].teleported = 0;
  2300.             bullet[7].visible    = bullet[8].visible    = TRUE;
  2301.             bullet[7].reflected  = bullet[8].reflected  = FALSE;
  2302.             if (!worm[player].deltax && worm[player].deltay)
  2303.             {   bullet[7].deltax = -1;
  2304.                 bullet[8].deltax = 1;
  2305.                 bullet[7].deltay = bullet[8].deltay = 0;
  2306.             } elif (worm[player].deltax && !worm[player].deltay)
  2307.             {   bullet[7].deltax = bullet[8].deltax = 0;
  2308.                 bullet[7].deltay = -1;
  2309.                 bullet[8].deltay = 1;
  2310.             } else /* worm is diagonal */
  2311.             {   if (worm[player].deltax == worm[player].deltay)
  2312.                 {   bullet[7].deltax = 1;
  2313.                     bullet[7].deltay = -1;
  2314.                 } else
  2315.                 {   bullet[7].deltax = -1;
  2316.                     bullet[7].deltay = -1;
  2317.                 }
  2318.                 bullet[8].deltax = -bullet[7].deltax;
  2319.                 bullet[8].deltay = -bullet[7].deltay;
  2320.             }
  2321.             bullet[7].x = worm[player].x + bullet[7].deltax;
  2322.             bullet[7].y = worm[player].y + bullet[7].deltay;
  2323.             bullet[8].x = worm[player].x + bullet[8].deltax;
  2324.             bullet[8].y = worm[player].y + bullet[8].deltay;
  2325.         }
  2326.  
  2327.         for (i = 0; i <= worm[player].power; i++)
  2328.         {   bullet[i].alive      = TRUE;
  2329.             bullet[i].teleported = 0;
  2330.             bullet[i].visible    = TRUE;
  2331.             bullet[i].reflected  = FALSE;
  2332.             bullet[i].deltax     = worm[player].deltax;
  2333.             bullet[i].deltay     = worm[player].deltay;
  2334.             if (i % 2 == 0)
  2335.                 distance = i / 2;
  2336.             else distance = -((i + 1) / 2);
  2337.             if (worm[player].deltax == 0)
  2338.             {   bullet[i].x = worm[player].x + distance;
  2339.                 bullet[i].y = worm[player].y + worm[player].deltay;
  2340.             } elif (worm[player].deltay == 0)
  2341.             {   bullet[i].x = worm[player].x + worm[player].deltax;
  2342.                 bullet[i].y = worm[player].y + distance;
  2343.             } else
  2344.             {   switch (i)
  2345.                 {
  2346.                 case 0:
  2347.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2348.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2349.                 break;
  2350.                 case 1:
  2351.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2352.                     bullet[i].y = worm[player].y;
  2353.                 break;
  2354.                 case 2:
  2355.                     bullet[i].x = worm[player].x;
  2356.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2357.                 break;
  2358.                 case 3:
  2359.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2360.                     bullet[i].y = worm[player].y;
  2361.                 break;
  2362.                 case 4:
  2363.                     bullet[i].x = worm[player].x;
  2364.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2365.                 break;
  2366.                 case 5:
  2367.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2368.                     bullet[i].y = worm[player].y - worm[player].deltay;
  2369.                 break;
  2370.                 case 6:
  2371.                     bullet[i].x = worm[player].x - worm[player].deltax;
  2372.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2373.                 break;
  2374.                 default:
  2375.                 break;
  2376.         }   }   }
  2377.  
  2378.         for (i = 0; i <= 8; i++)
  2379.         {   if (bullet[i].alive && (!valid(bullet[i].x, bullet[i].y)))
  2380.             {    bullet[i].alive = FALSE;
  2381.         }   }
  2382.  
  2383.         /* Bullets are now set up. */
  2384.  
  2385.         finished = FALSE;
  2386.         while (!finished)
  2387.         {   finished = TRUE;
  2388.             for (i = 0; i <= 8; i++)
  2389.             {   if (bullet[i].alive)
  2390.                 {   if (bullet[i].visible)
  2391.                     {   if (worm[player].remnants)
  2392.                             change(bullet[i].x, bullet[i].y, FIRSTGLOW + player);
  2393.                         else change(bullet[i].x, bullet[i].y, EMPTY);
  2394.                     }
  2395.  
  2396.                     finished = FALSE;
  2397.                     bullet[i].visible = TRUE;
  2398.                     if (bullet[i].reflected)
  2399.                     {   bullet[i].x -= bullet[i].deltax;
  2400.                         bullet[i].y -= bullet[i].deltay;
  2401.                     } else
  2402.                     {   bullet[i].x += bullet[i].deltax;
  2403.                         bullet[i].y += bullet[i].deltay;
  2404.                     }
  2405.                     x = bullet[i].x;
  2406.                     y = bullet[i].y;
  2407.                     c = field[x][y];
  2408.                     if (!(valid(x, y)))
  2409.                         bullet[i].alive = FALSE;
  2410.                     elif (x == worm[player].x && y == worm[player].y)
  2411.                     {   /* hit by own bullet */
  2412.                         bullet[i].alive = FALSE;
  2413.                         if (worm[player].armour == 0)
  2414.                         {   worm[player].cause = FIRSTFIRE + player;
  2415.                             worm[player].victor = -1;
  2416.                             worm[player].alive = FALSE;
  2417.                     }   }
  2418.                     elif (c >= FIRSTHEAD && c <= LASTHEAD)
  2419.                     {   if (worm[c - FIRSTHEAD].armour == 0)
  2420.                         {   worm[c - FIRSTHEAD].cause = FIRSTFIRE + player;
  2421.                             worm[c - FIRSTHEAD].victor = player;
  2422.                             worm[c - FIRSTHEAD].alive = FALSE;
  2423.                         } else effect(FXUSE_ARMOUR);
  2424.                         bullet[i].alive = FALSE;
  2425.                     } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  2426.                     {   if (player != c - FIRSTPROTECTOR)
  2427.                         {   effect(FXBORN_PROTECTOR);
  2428.                             bullet[i].alive = FALSE;
  2429.                         } else bullet[i].visible = FALSE;
  2430.                     } elif (c >= FIRSTNUMBER && c <= LASTNUMBER)
  2431.                     {   final = getnumber(player);
  2432.                         numbered = TRUE;
  2433.                     } elif (c >= FIRSTGRAVE && c <= LASTGRAVE)
  2434.                     {   bullet[i].alive = FALSE;
  2435.                     } else
  2436.                     {   switch(c)
  2437.                         {
  2438.                         case MINIBOMB:
  2439.                             // sets it off, for your benefit
  2440.                             bullet[i].alive = FALSE;
  2441.                             bombblast(HEAD, player, x, y, FALSE);
  2442.                         break;
  2443.                         case SUPERBOMB:
  2444.                             // sets it off, for your benefit
  2445.                             bullet[i].alive = FALSE;
  2446.                             bombblast(HEAD, player, x, y, TRUE);
  2447.                         break;
  2448.                         case SLIME:
  2449.                         case WOOD:
  2450.                             // destroys one layer of it
  2451.                             bullet[i].alive = FALSE;
  2452.                             change(x, y, EMPTY);
  2453.                         break;
  2454.                         case METAL:
  2455.                             if (bullet[i].reflected)
  2456.                                 bullet[i].alive = FALSE;
  2457.                             else
  2458.                             {   bullet[i].reflected = TRUE;
  2459.                                 bullet[i].x -= bullet[i].deltax * 2;
  2460.                                 bullet[i].y -= bullet[i].deltay * 2;
  2461.                             }
  2462.                             break;
  2463.                         case STONE:
  2464.                         case START:
  2465.                             bullet[i].alive = FALSE;
  2466.                         break;
  2467.                         case TELEPORT:
  2468.                             j = whichteleport(bullet[i].x, bullet[i].y);
  2469.                             if (bullet[i].teleported == 2 || blockedtel(j, bullet[i].deltax, bullet[i].deltay))
  2470.                             {   bullet[i].alive = FALSE;
  2471.                             } else
  2472.                             {   effect(FXUSE_TELEPORT);
  2473.                                 bullet[i].visible = FALSE;
  2474.                                 bullet[i].teleported++;
  2475.                                 bullet[i].x = teleport[partner(j)].x;
  2476.                                 bullet[i].y = teleport[partner(j)].y;
  2477.                             }
  2478.                         break;
  2479.                         default:
  2480.                             if (c >= FIRSTCREATURE)
  2481.                             {   j = whichcreature(x, y, c, 255);
  2482.                                 bullet[i].alive = FALSE;
  2483.                                 wormkillcreature(player, j, TRUE);
  2484.                                 change(x, y, FIRSTFLOWER + player);
  2485.                             } elif (c <= LASTOBJECT)
  2486.                             {   bullet[i].alive = FALSE;
  2487.                                 change(x, y, FIRSTCHERRY + player);
  2488.                             }
  2489.                         break;
  2490.                     }   }
  2491.  
  2492.                     // x and y need this refreshing here
  2493.                     x = bullet[i].x;
  2494.                     y = bullet[i].y;
  2495.                     if (bullet[i].alive && bullet[i].visible)
  2496.                     {   draw(x, y, FIRSTFIRE + player);
  2497.         }   }   }   }
  2498.         if (numbered && !final)
  2499.         {   putnumber();
  2500.         }
  2501.         clearkybd();
  2502. }   }
  2503.  
  2504. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay)
  2505. {   if (creature[which].pos < DOGQUEUELIMIT)
  2506.     {   creature[which].pos++;
  2507.         thedogqueue[which][creature[which].pos].deltax = deltax;
  2508.         thedogqueue[which][creature[which].pos].deltay = deltay;
  2509.     } else
  2510.     {   creature[which].alive = FALSE;
  2511.         change(creature[which].x, creature[which].y, EMPTY);
  2512. }   }
  2513.  
  2514. /* NAME     queue -- adds a keystroke to the key queue
  2515. SYNOPSIS    name(SBYTE, SBYTE, SBYTE);
  2516. FUNCTION    Adds a keystroke to the in-game key queue.
  2517. INPUTS      player - player that pressed the key
  2518.             deltax - the deltax of the key
  2519.             deltay - the deltay of the key
  2520. IMPLEMENTATION
  2521.             thewormqueue[] array has WORMQUEUELIMIT as its last index.
  2522.             It is implemented as a FIFO stack rather than LIFO so that
  2523.             the keystrokes are processed in the correct order (that is,
  2524.             the order in which they were pressed). The oldest keystroke
  2525.             is always at index [0], the next oldest at [1], and so on
  2526.             upwards to the newest keystroke, at [worm[player].pos].
  2527.             Keystrokes are removed from the bottom of the array ([0]),
  2528.             and the rest of the array is shuffled down to fill the gap,
  2529.             so that the contents of [1] go to [0], the contents of [2]
  2530.             go to [1], etc. worm[player].pos is adjusted to always point
  2531.             to the newest entry, which is the 'end' of the queue.
  2532. MODULE      engine2.c */
  2533.  
  2534. AGLOBAL void wormqueue(SBYTE player, SBYTE deltax, SBYTE deltay)
  2535. {   if (worm[player].pos < WORMQUEUELIMIT)
  2536.     {   worm[player].pos++;
  2537.         thewormqueue[player][worm[player].pos].deltax = deltax;
  2538.         thewormqueue[player][worm[player].pos].deltay = deltay;
  2539. }   }
  2540.  
  2541. AGLOBAL void drawcreature(UBYTE which)
  2542. {   switch(creature[which].species)
  2543.     {
  2544.     case BIRD:
  2545.         draw(creature[which].x, creature[which].y, birdframes[creature[which].frame]);
  2546.     break;
  2547.     case BULL:
  2548.         if (creature[which].dir == -1)
  2549.         {   draw(creature[which].x, creature[which].y, BULLLEFT);
  2550.         } else
  2551.         {   // assert(creature[which].dir == 1);
  2552.             draw(creature[which].x, creature[which].y, BULLRIGHT);
  2553.         }
  2554.     break;
  2555.     case RABBIT:
  2556.         if (creature[which].deltax == -1)
  2557.         {   draw(creature[which].x, creature[which].y, RABBITLEFT);
  2558.         } else
  2559.         {   // assert(creature[which].deltax == 1);
  2560.             draw(creature[which].x, creature[which].y, RABBITRIGHT);
  2561.         }
  2562.     break;
  2563.     case DOG:
  2564.         if (creature[which].dormant == 0)
  2565.         {   draw(creature[which].x, creature[which].y, DOGDORMANT);
  2566.         } elif (creature[which].dormant < CHASING)
  2567.         {   draw(creature[which].x, creature[which].y, DOGAWAKENING);
  2568.         } else
  2569.         {   draw(creature[which].x, creature[which].y, DOGCHASING);
  2570.         }
  2571.     break;
  2572.     case RAIN:
  2573.         draw(creature[which].x, creature[which].y, FIRSTRAIN + creature[which].player);
  2574.     break;
  2575.     case FRAGMENT:
  2576.         if (creature[which].subspecies == FRAGMENT)
  2577.         {   draw(creature[which].x, creature[which].y, FRAGMENT);
  2578.         } else
  2579.         {   // assert(creature[which].subspecies == BANANA);
  2580.             draw(creature[which].x, creature[which].y, bananaframes[creature[which].player][creature[which].frame]);
  2581.         }
  2582.     break;
  2583.     case FROG:
  2584.         if (creature[which].dir == -1)
  2585.         {   draw(creature[which].x, creature[which].y, FROGLEFT);
  2586.         } else
  2587.         {   // assert(creature[which].dir == 1);
  2588.             draw(creature[which].x, creature[which].y, FROGRIGHT);
  2589.         }
  2590.     break;
  2591.     case MISSILE_C:
  2592.         draw(creature[which].x, creature[which].y, missileframes[creature[which].player][creature[which].frame]);
  2593.     break;
  2594.     default:
  2595.         draw(creature[which].x, creature[which].y, creature[which].species);
  2596.     break;
  2597.     }
  2598.  
  2599.     field[creature[which].x][creature[which].y] = creature[which].species;
  2600. }
  2601.  
  2602. AGLOBAL ABOOL blockedsquare(SBYTE x, SBYTE y)
  2603. {   UBYTE c = field[x][y];
  2604.  
  2605.     if
  2606.     (   c == STONE
  2607.      || c == METAL
  2608.      || c == WOOD
  2609.      || (c >= FIRSTCREATURE && creatureinfo[c - FIRSTCREATURE].wall)
  2610.     )
  2611.     {   return TRUE;
  2612.     } else
  2613.     {   return FALSE;
  2614. }   }
  2615.  
  2616. MODULE void choosediagonal(UBYTE which)
  2617. {   SBYTE number;
  2618.  
  2619.     /* This routine is a workaround for a very strange bug. */
  2620.  
  2621.     do
  2622.     {   number = arand(3);
  2623.         switch(number)
  2624.         {
  2625.         case 0:
  2626.             creature[which].deltax = -1;
  2627.             creature[which].deltay = -1;
  2628.         break;
  2629.         case 1:
  2630.             creature[which].deltax = -1;
  2631.             creature[which].deltay =  1;
  2632.         break;
  2633.         case 2:
  2634.             creature[which].deltax =  1;
  2635.             creature[which].deltay = -1;
  2636.         break;
  2637.         case 3:
  2638.             creature[which].deltax =  1;
  2639.             creature[which].deltay =  1;
  2640.         break;
  2641.         default:
  2642.             // assert(0);
  2643.         break;
  2644.         } // end switch
  2645.     } while (!valid(creature[which].x + creature[which].deltax, creature[which].y + creature[which].deltay));
  2646. }
  2647.  
  2648. MODULE void chooseorthagonal(SBYTE* xx, SBYTE* yy)
  2649. {   SBYTE number;
  2650.  
  2651.     /* This routine is a workaround for a very strange bug. */
  2652.  
  2653.     number = arand(3);
  2654.     switch(number)
  2655.     {
  2656.     case 0:
  2657.         *xx =  0;
  2658.         *yy = -1;
  2659.     break;
  2660.     case 1:
  2661.         *xx =  0;
  2662.         *yy =  1;
  2663.     break;
  2664.     case 2:
  2665.         *xx = -1;
  2666.         *yy =  0;
  2667.     break;
  2668.     case 3:
  2669.         *xx =  1;
  2670.         *yy =  0;
  2671.     break;
  2672.     default:
  2673.         // assert(0);
  2674.     break;
  2675. }   }
  2676.  
  2677. AGLOBAL void stoppedwormloop(SBYTE player)
  2678. {    SBYTE i;
  2679.     FLAG go = FALSE;
  2680.  
  2681.     /* remove a keystroke from the worm queue
  2682.     The worm still has deltax and deltay whilst stopped. */
  2683.  
  2684.     if (!(r % SPEED_PROTECTOR))
  2685.     {    protectorloop1(player);
  2686.         protectorloop2(player);
  2687.     } // affixer becomes a disadvantage in this situation
  2688.  
  2689.     if (worm[player].pos != -1)                         
  2690.     {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  2691.         {   if (worm[player].ammo)
  2692.             {    wormbullet(player); // you can fire bullets whilst stopped :-)
  2693.         }    }
  2694.         elif
  2695.         (    thewormqueue[player][0].deltax != -worm[player].deltax
  2696.          || thewormqueue[player][0].deltay != -worm[player].deltay
  2697.         )
  2698.         {    worm[player].speed = SLOW;
  2699.             stat(player, BRAKES);
  2700.             worm[player].deltax = thewormqueue[player][0].deltax;
  2701.             worm[player].deltay = thewormqueue[player][0].deltay;
  2702.             worm[player].frosted = FALSE;
  2703.             go = TRUE;
  2704.         }
  2705.         if (--worm[player].pos != -1)
  2706.         {   for (i = 0; i <= worm[player].pos; i++)
  2707.             {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  2708.                 thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  2709.          }   }
  2710.         if (go)
  2711.         {    wormloop(player);
  2712.             worm[player].wait = TRUE;
  2713. }    }    }
  2714.  
  2715. MODULE void protectorloop1(SBYTE player)
  2716. {    SBYTE i;
  2717.  
  2718.     // move protectors
  2719.  
  2720.     for (i = 0; i <= PROTECTORS; i++)
  2721.     {   if (protector[player][i].alive)
  2722.         {   if (protector[player][i].visible)
  2723.             {   change(protector[player][i].x, protector[player][i].y, protector[player][i].last);
  2724.             } else protector[player][i].visible = TRUE;
  2725.             protector[player][i].last = EMPTY;
  2726.             if (i == NOSE)
  2727.             {   protector[player][i].relx = worm[player].deltax * DISTANCE_NOSE;
  2728.                 protector[player][i].rely = worm[player].deltay * DISTANCE_NOSE;
  2729.                 if (!worm[player].affixer)
  2730.                 {   if (worm[player].position == -1)
  2731.                         worm[player].posidir = 1;
  2732.                     elif (worm[player].position == 1)
  2733.                         worm[player].posidir = -1;
  2734.                     worm[player].position += worm[player].posidir;
  2735.                     if (worm[player].deltax == 0)
  2736.                         protector[player][i].relx = worm[player].position;
  2737.                     elif (worm[player].deltay == 0)
  2738.                         protector[player][i].rely = worm[player].position;
  2739.                     elif (worm[player].position == -1)
  2740.                         protector[player][i].relx = worm[player].deltax * (DISTANCE_NOSE - 1);
  2741.                     elif (worm[player].position == 1)
  2742.                         protector[player][i].rely = worm[player].deltay * (DISTANCE_NOSE - 1);
  2743.             }   }
  2744.             elif (!worm[player].affixer)
  2745.             {   if (protector[player][i].relx == 1 && protector[player][i].rely == -1)
  2746.                 {   protector[player][i].deltax = 0;
  2747.                     protector[player][i].deltay = 1;
  2748.                 } elif (protector[player][i].relx == 1 && protector[player][i].rely == 1)
  2749.                 {   protector[player][i].deltax = -1;
  2750.                     protector[player][i].deltay = 0;
  2751.                 } elif (protector[player][i].relx == -1 && protector[player][i].rely == 1)
  2752.                 {   protector[player][i].deltax = 0;
  2753.                     protector[player][i].deltay = -1;
  2754.                 } elif (protector[player][i].relx == -1 && protector[player][i].rely == -1)
  2755.                 {   protector[player][i].deltax = 1;
  2756.                     protector[player][i].deltay = 0;
  2757.                 }
  2758.                 protector[player][i].relx += protector[player][i].deltax;
  2759.                 protector[player][i].rely += protector[player][i].deltay;
  2760.             }
  2761.             protector[player][i].x = worm[player].x + protector[player][i].relx;
  2762.             protector[player][i].y = worm[player].y + protector[player][i].rely;
  2763.             if (!valid(protector[player][i].x, protector[player][i].y))
  2764.             {   protector[player][i].visible = FALSE;
  2765. }   }   }   }
  2766.  
  2767. MODULE void protectorloop2(SBYTE player)
  2768. {   SBYTE thisprot;
  2769.  
  2770.     // protector collision detection
  2771.     for (thisprot = 0; thisprot <= PROTECTORS; thisprot++)
  2772.     {   if (protector[player][thisprot].alive && protector[player][thisprot].visible)
  2773.         {   protcol(player, protector[player][thisprot].x, protector[player][thisprot].y, thisprot);
  2774.  
  2775.             // we now need to recheck whether the protector should be visible or not
  2776.             // this might be defensive programming to hide a bug, or might be legitimate
  2777.             if (!valid(protector[player][thisprot].x, protector[player][thisprot].y))
  2778.             {   protector[player][thisprot].visible = FALSE;
  2779.             }
  2780.  
  2781.             // draw protector
  2782.             if (protector[player][thisprot].alive && protector[player][thisprot].visible) // in case protector has just been killed, etc.
  2783.             {   change(protector[player][thisprot].x, protector[player][thisprot].y, FIRSTPROTECTOR + player);
  2784. }   }   }   }
  2785.  
  2786. MODULE void turncreature(UBYTE which)
  2787. {    switch(creature[which].dir)
  2788.                 {   case 0:
  2789.                                     creature[which].deltax = 0;
  2790.                                     creature[which].deltay = -1;
  2791.                                 break;
  2792.                                 case 1:
  2793.                                     creature[which].deltax = 1;
  2794.                                     creature[which].deltay = -1;
  2795.                                 break;
  2796.                                 case 2:
  2797.                                     creature[which].deltax = 1;
  2798.                                     creature[which].deltay = 0;
  2799.                                 break;
  2800.                                 case 3:
  2801.                                     creature[which].deltax = 1;
  2802.                                     creature[which].deltay = 1;
  2803.                                 break;
  2804.                                 case 4:
  2805.                                     creature[which].deltax = 0;
  2806.                                     creature[which].deltay = 1;
  2807.                                 break;
  2808.                                 case 5:
  2809.                                     creature[which].deltax = -1;
  2810.                                     creature[which].deltay = 1;
  2811.                                 break;
  2812.                                 case 6:
  2813.                                     creature[which].deltax = -1;
  2814.                                     creature[which].deltay = 0;
  2815.                                 break;
  2816.                                 case 7:
  2817.                                     creature[which].deltax = -1;
  2818.                                     creature[which].deltay = -1;
  2819.                                 break;
  2820.                                 default:
  2821.                                     // assert(0);
  2822.                                     creature[which].deltax = creature[which].deltay = 0; // to avoid spurious warnings
  2823.                                 break;
  2824.                                 }
  2825. }
  2826.